6 #ifndef GDCORE_EXPRESSIONPARSER2_H
7 #define GDCORE_EXPRESSIONPARSER2_H
13 #include "ExpressionParser2Node.h"
14 #include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
15 #include "GDCore/Extensions/Metadata/MetadataProvider.h"
16 #include "GDCore/Extensions/Metadata/ObjectMetadata.h"
17 #include "GDCore/Project/Layout.h"
18 #include "GDCore/String.h"
20 #include "GDCore/Tools/MakeUnique.h"
21 #include "GrammarTerminals.h"
24 class ObjectsContainer;
26 class ParameterMetadata;
27 class ExpressionMetadata;
65 expressionUtf32 = expression.
ToUTF32();
84 return !behaviorName.
empty() ? 2 : (!objectName.
empty() ? 1 : 0);
92 std::unique_ptr<ExpressionNode> Start() {
93 size_t expressionStartPosition = GetCurrentPosition();
97 if (!IsEndReached()) {
98 auto op = gd::make_unique<OperatorNode>(
' ');
99 op->leftHandSide = std::move(expression);
100 op->rightHandSide = ReadUntilEnd();
101 op->rightHandSide->parent = op.get();
103 op->rightHandSide->diagnostic = RaiseSyntaxError(
104 _(
"The expression has extra character at the end that should be "
105 "removed (or completed if your expression is not finished)."));
108 GetCurrentPosition());
109 return std::move(op);
115 std::unique_ptr<ExpressionNode> Expression() {
116 SkipAllWhitespaces();
118 size_t expressionStartPosition = GetCurrentPosition();
119 std::unique_ptr<ExpressionNode> leftHandSide = Term();
121 SkipAllWhitespaces();
123 if (IsEndReached())
return leftHandSide;
124 if (CheckIfChar(IsExpressionEndingChar))
return leftHandSide;
125 if (CheckIfChar(IsExpressionOperator)) {
126 auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
127 op->leftHandSide = std::move(leftHandSide);
128 op->leftHandSide->parent = op.get();
129 op->diagnostic = ValidateOperator(GetCurrentChar());
131 op->rightHandSide = Expression();
132 op->rightHandSide->parent = op.get();
134 op->location = ExpressionParserLocation(expressionStartPosition,
135 GetCurrentPosition());
136 return std::move(op);
139 leftHandSide->diagnostic = RaiseSyntaxError(
140 "More than one term was found. Verify that your expression is "
141 "properly written.");
143 auto op = gd::make_unique<OperatorNode>(
' ');
144 op->leftHandSide = std::move(leftHandSide);
145 op->leftHandSide->parent = op.get();
146 op->rightHandSide = Expression();
147 op->rightHandSide->parent = op.get();
149 ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
150 return std::move(op);
153 std::unique_ptr<ExpressionNode> Term() {
154 SkipAllWhitespaces();
156 size_t expressionStartPosition = GetCurrentPosition();
157 std::unique_ptr<ExpressionNode> factor = Factor();
159 SkipAllWhitespaces();
164 while (CheckIfChar(IsTermOperator)) {
165 auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
166 op->leftHandSide = std::move(factor);
167 op->leftHandSide->parent = op.get();
168 op->diagnostic = ValidateOperator(GetCurrentChar());
170 op->rightHandSide = Factor();
171 op->rightHandSide->parent = op.get();
172 op->location = ExpressionParserLocation(expressionStartPosition,
173 GetCurrentPosition());
174 SkipAllWhitespaces();
176 factor = std::move(op);
182 std::unique_ptr<ExpressionNode> Factor() {
183 SkipAllWhitespaces();
184 size_t expressionStartPosition = GetCurrentPosition();
186 if (CheckIfChar(IsQuote)) {
187 std::unique_ptr<ExpressionNode> factor = ReadText();
189 }
else if (CheckIfChar(IsUnaryOperator)) {
190 auto unaryOperatorCharacter = GetCurrentChar();
192 bool isNumberSign = CheckIfChar(IsNumberSign);
194 if (isNumberSign && CheckIfChar(IsNumberFirstChar)) {
195 std::unique_ptr<ExpressionNode> numberNode =
196 ReadNumber(expressionStartPosition);
199 auto operatorOperand = Factor();
201 auto unaryOperator = gd::make_unique<UnaryOperatorNode>(
202 unaryOperatorCharacter);
203 unaryOperator->diagnostic = ValidateUnaryOperator(
204 unaryOperatorCharacter, expressionStartPosition);
205 unaryOperator->factor = std::move(operatorOperand);
206 unaryOperator->factor->parent = unaryOperator.get();
207 unaryOperator->location = ExpressionParserLocation(
208 expressionStartPosition, GetCurrentPosition());
210 return std::move(unaryOperator);
211 }
else if (CheckIfChar(IsNumberFirstChar)) {
212 std::unique_ptr<ExpressionNode> factor = ReadNumber();
214 }
else if (CheckIfChar(IsOpeningParenthesis)) {
215 size_t expressionStartPosition = GetCurrentPosition();
219 auto expression = Expression();
222 auto factor = gd::make_unique<SubExpressionNode>(std::move(expression));
224 if (!CheckIfChar(IsClosingParenthesis)) {
226 RaiseSyntaxError(_(
"Missing a closing parenthesis. Add a closing "
227 "parenthesis for each opening parenthesis."));
229 SkipIfChar(IsClosingParenthesis);
230 factor->location = ExpressionParserLocation(expressionStartPosition,
231 GetCurrentPosition());
233 return std::move(factor);
238 std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace();
242 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
244 auto identifierAndLocation = ReadIdentifierName();
246 auto nameLocation = identifierAndLocation.location;
248 SkipAllWhitespaces();
255 if (IsNamespaceSeparator()) {
256 SkipNamespaceSeparator();
257 SkipAllWhitespaces();
259 auto postNamespaceIdentifierAndLocation = ReadIdentifierName();
260 name += NAMESPACE_SEPARATOR;
261 name += postNamespaceIdentifierAndLocation.name;
262 ExpressionParserLocation completeNameLocation(
263 nameLocation.GetStartPosition(),
264 postNamespaceIdentifierAndLocation.location.GetEndPosition());
265 nameLocation = completeNameLocation;
268 if (CheckIfChar(IsOpeningParenthesis)) {
269 ExpressionParserLocation openingParenthesisLocation = SkipChar();
270 return FreeFunction(name, nameLocation, openingParenthesisLocation);
271 }
else if (CheckIfChar(IsDot)) {
272 ExpressionParserLocation dotLocation = SkipChar();
273 SkipAllWhitespaces();
274 return ObjectFunctionOrBehaviorFunctionOrVariable(
275 name, nameLocation, dotLocation);
276 }
else if (CheckIfChar(IsOpeningSquareBracket)) {
277 return Variable(name, nameLocation);
279 auto identifier = gd::make_unique<IdentifierNode>(name);
280 identifier->location = ExpressionParserLocation(
281 nameLocation.GetStartPosition(), GetCurrentPosition());
282 identifier->identifierNameLocation = identifier->location;
283 return std::move(identifier);
288 auto variable = gd::make_unique<VariableNode>(name);
290 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
291 variable->child = VariableAccessorOrVariableBracketAccessor();
292 variable->child->parent = variable.get();
295 variable->location = ExpressionParserLocation(
296 nameLocation.GetStartPosition(), GetCurrentPosition());
297 variable->nameLocation = nameLocation;
298 return std::move(variable);
301 std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
302 VariableAccessorOrVariableBracketAccessor() {
303 size_t childStartPosition = GetCurrentPosition();
305 SkipAllWhitespaces();
306 if (CheckIfChar(IsOpeningSquareBracket)) {
308 auto child = gd::make_unique<VariableBracketAccessorNode>(Expression());
309 child->expression->parent = child.get();
311 if (!CheckIfChar(IsClosingSquareBracket)) {
313 RaiseSyntaxError(_(
"Missing a closing bracket. Add a closing "
314 "bracket for each opening bracket."));
316 SkipIfChar(IsClosingSquareBracket);
318 SkipAllWhitespaces();
319 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
320 child->child = VariableAccessorOrVariableBracketAccessor();
321 child->child->parent = child.get();
324 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
326 return std::move(child);
327 }
else if (CheckIfChar(IsDot)) {
328 auto dotLocation = SkipChar();
329 SkipAllWhitespaces();
331 auto identifierAndLocation = ReadIdentifierName(
false);
333 gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
334 if (identifierAndLocation.name.empty()) {
335 child->diagnostic = RaiseSyntaxError(_(
"A name should be entered after the dot."));
338 SkipAllWhitespaces();
339 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
340 child->child = VariableAccessorOrVariableBracketAccessor();
341 child->child->parent = child.get();
343 child->nameLocation = identifierAndLocation.location;
344 child->dotLocation = dotLocation;
346 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
348 return std::move(child);
353 auto unrecognisedNode = gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>();
354 unrecognisedNode->diagnostic = RaiseSyntaxError(_(
"A dot or bracket was expected here."));
355 return std::move(unrecognisedNode);
358 std::unique_ptr<FunctionCallNode> FreeFunction(
360 const ExpressionParserLocation &identifierLocation,
361 const ExpressionParserLocation &openingParenthesisLocation) {
366 gd::make_unique<FunctionCallNode>(functionFullName);
367 auto parametersNode = Parameters(
function.get());
368 function->parameters = std::move(parametersNode.parameters);
369 function->diagnostic = std::move(parametersNode.diagnostic);
371 function->location = ExpressionParserLocation(
372 identifierLocation.GetStartPosition(), GetCurrentPosition());
373 function->functionNameLocation = identifierLocation;
374 function->openingParenthesisLocation = openingParenthesisLocation;
375 function->closingParenthesisLocation =
376 parametersNode.closingParenthesisLocation;
378 return std::move(
function);
381 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
382 ObjectFunctionOrBehaviorFunctionOrVariable(
384 const ExpressionParserLocation &parentIdentifierLocation,
385 const ExpressionParserLocation &parentIdentifierDotLocation) {
386 auto childIdentifierAndLocation = ReadIdentifierName(
false);
387 const gd::String &childIdentifierName = childIdentifierAndLocation.name;
388 const auto &childIdentifierNameLocation =
389 childIdentifierAndLocation.location;
391 std::unique_ptr<gd::ExpressionParserError> emptyNameError = childIdentifierName.
empty() ?
392 RaiseSyntaxError(_(
"A name should be entered after the dot.")) : nullptr;
394 SkipAllWhitespaces();
396 if (IsNamespaceSeparator()) {
397 ExpressionParserLocation namespaceSeparatorLocation =
398 SkipNamespaceSeparator();
399 SkipAllWhitespaces();
400 auto behaviorFunction = BehaviorFunction(parentIdentifier,
402 parentIdentifierLocation,
403 parentIdentifierDotLocation,
404 childIdentifierNameLocation,
405 namespaceSeparatorLocation);
407 if (emptyNameError) behaviorFunction->diagnostic = std::move(emptyNameError);
408 return std::move(behaviorFunction);
409 }
else if (CheckIfChar(IsOpeningParenthesis)) {
410 ExpressionParserLocation openingParenthesisLocation = SkipChar();
412 auto function = gd::make_unique<FunctionCallNode>(
414 childIdentifierName);
415 auto parametersNode = Parameters(
function.get(), parentIdentifier);
416 function->parameters = std::move(parametersNode.parameters),
417 function->diagnostic = emptyNameError ? std::move(emptyNameError) : std::move(parametersNode.diagnostic);
419 function->location = ExpressionParserLocation(
420 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
421 function->objectNameLocation = parentIdentifierLocation;
422 function->objectNameDotLocation = parentIdentifierDotLocation;
423 function->functionNameLocation = childIdentifierNameLocation;
424 function->openingParenthesisLocation = openingParenthesisLocation;
425 function->closingParenthesisLocation =
426 parametersNode.closingParenthesisLocation;
427 return std::move(
function);
428 }
else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
429 auto variable = gd::make_unique<VariableNode>(parentIdentifier);
430 variable->diagnostic = std::move(emptyNameError);
433 gd::make_unique<VariableAccessorNode>(childIdentifierName);
434 child->child = VariableAccessorOrVariableBracketAccessor();
435 child->child->parent = child.get();
436 child->nameLocation = childIdentifierNameLocation;
437 child->dotLocation = parentIdentifierDotLocation;
438 child->location = ExpressionParserLocation(
439 parentIdentifierDotLocation.GetStartPosition(), GetCurrentPosition());
440 variable->child = std::move(child);
441 variable->child->parent = variable.get();
443 variable->location = ExpressionParserLocation(
444 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
445 variable->nameLocation = parentIdentifierLocation;
447 return std::move(variable);
450 auto node = gd::make_unique<IdentifierNode>(
451 parentIdentifier, childIdentifierName);
452 node->location = ExpressionParserLocation(
453 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
454 node->identifierNameLocation = parentIdentifierLocation;
455 node->identifierNameDotLocation = parentIdentifierDotLocation;
456 node->childIdentifierNameLocation = childIdentifierNameLocation;
457 node->diagnostic = std::move(emptyNameError);
458 return std::move(node);
461 std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction(
464 const ExpressionParserLocation &objectNameLocation,
465 const ExpressionParserLocation &objectNameDotLocation,
466 const ExpressionParserLocation &behaviorNameLocation,
467 const ExpressionParserLocation &behaviorNameNamespaceSeparatorLocation) {
468 auto identifierAndLocation = ReadIdentifierName();
469 const gd::String &functionName = identifierAndLocation.name;
470 const auto &functionNameLocation = identifierAndLocation.location;
472 SkipAllWhitespaces();
474 if (CheckIfChar(IsOpeningParenthesis)) {
475 ExpressionParserLocation openingParenthesisLocation = SkipChar();
477 auto function = gd::make_unique<FunctionCallNode>(
481 auto parametersNode =
482 Parameters(
function.get(), objectName, behaviorName);
483 function->parameters = std::move(parametersNode.parameters);
484 function->diagnostic = std::move(parametersNode.diagnostic);
486 function->location = ExpressionParserLocation(
487 objectNameLocation.GetStartPosition(), GetCurrentPosition());
488 function->objectNameLocation = objectNameLocation;
489 function->objectNameDotLocation = objectNameDotLocation;
490 function->behaviorNameLocation = behaviorNameLocation;
491 function->behaviorNameNamespaceSeparatorLocation =
492 behaviorNameNamespaceSeparatorLocation;
493 function->openingParenthesisLocation = openingParenthesisLocation;
494 function->closingParenthesisLocation =
495 parametersNode.closingParenthesisLocation;
496 function->functionNameLocation = functionNameLocation;
497 return std::move(
function);
499 auto node = gd::make_unique<ObjectFunctionNameNode>(
500 objectName, behaviorName, functionName);
501 node->diagnostic = RaiseSyntaxError(
502 _(
"An opening parenthesis was expected here to call a function."));
504 node->location = ExpressionParserLocation(
505 objectNameLocation.GetStartPosition(), GetCurrentPosition());
506 node->objectNameLocation = objectNameLocation;
507 node->objectNameDotLocation = objectNameDotLocation;
508 node->objectFunctionOrBehaviorNameLocation = behaviorNameLocation;
509 node->behaviorNameNamespaceSeparatorLocation =
510 behaviorNameNamespaceSeparatorLocation;
511 node->behaviorFunctionNameLocation = functionNameLocation;
512 return std::move(node);
517 struct ParametersNode {
518 std::vector<std::unique_ptr<ExpressionNode>> parameters;
519 std::unique_ptr<gd::ExpressionParserError> diagnostic;
520 ExpressionParserLocation closingParenthesisLocation;
523 ParametersNode Parameters(
524 FunctionCallNode *functionCallNode,
527 std::vector<std::unique_ptr<ExpressionNode>> parameters;
530 bool previousCharacterIsParameterSeparator =
false;
531 while (!IsEndReached()) {
532 SkipAllWhitespaces();
534 if (CheckIfChar(IsClosingParenthesis) && !previousCharacterIsParameterSeparator) {
535 auto closingParenthesisLocation = SkipChar();
536 return ParametersNode{
537 std::move(parameters),
nullptr, closingParenthesisLocation};
539 bool isEmptyParameter = CheckIfChar(IsParameterSeparator)
540 || (CheckIfChar(IsClosingParenthesis) && previousCharacterIsParameterSeparator);
541 auto parameter = isEmptyParameter ? gd::make_unique<EmptyNode>() : Expression();
542 parameter->parent = functionCallNode;
543 parameters.push_back(std::move(parameter));
545 SkipAllWhitespaces();
546 previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
547 SkipIfChar(IsParameterSeparator);
550 ExpressionParserLocation invalidClosingParenthesisLocation;
551 return ParametersNode{
552 std::move(parameters),
553 RaiseSyntaxError(_(
"The list of parameters is not terminated. Add a "
554 "closing parenthesis to end the parameters.")),
555 invalidClosingParenthesisLocation};
559 std::unique_ptr<ExpressionParserError> ValidateOperator(
560 gd::String::value_type operatorChar) {
561 if (operatorChar ==
'+' || operatorChar ==
'-' || operatorChar ==
'/' ||
562 operatorChar ==
'*') {
563 return std::unique_ptr<ExpressionParserError>(
nullptr);
565 return gd::make_unique<ExpressionParserError>(
566 gd::ExpressionParserError::ErrorType::InvalidOperator,
567 _(
"You've used an operator that is not supported. Operator should be "
568 "either +, -, / or *."),
569 GetCurrentPosition());
572 std::unique_ptr<ExpressionParserError> ValidateUnaryOperator(
573 gd::String::value_type operatorChar,
575 if (operatorChar ==
'+' || operatorChar ==
'-') {
576 return std::unique_ptr<ExpressionParserError>(
nullptr);
579 return gd::make_unique<ExpressionParserError>(
580 gd::ExpressionParserError::ErrorType::InvalidOperator,
581 _(
"You've used an \"unary\" operator that is not supported. Operator "
592 ExpressionParserLocation SkipChar() {
593 size_t startPosition = currentPosition;
594 return ExpressionParserLocation(startPosition, ++currentPosition);
597 void SkipAllWhitespaces() {
598 while (currentPosition < expressionUtf32.size() &&
599 IsWhitespace(expressionUtf32[currentPosition])) {
605 const std::function<
bool(gd::String::value_type)> &predicate) {
606 if (CheckIfChar(predicate)) {
611 ExpressionParserLocation SkipNamespaceSeparator() {
612 size_t startPosition = currentPosition;
615 if (IsNamespaceSeparator()) {
616 currentPosition += NAMESPACE_SEPARATOR.size();
619 return ExpressionParserLocation(startPosition, currentPosition);
623 const std::function<
bool(gd::String::value_type)> &predicate) {
624 if (currentPosition >= expressionUtf32.size())
return false;
625 gd::String::value_type character = expressionUtf32[currentPosition];
627 return predicate(character);
630 bool IsNamespaceSeparator() {
633 static const std::u32string separator = NAMESPACE_SEPARATOR.ToUTF32();
634 return (currentPosition + separator.size() <= expressionUtf32.size() &&
635 expressionUtf32.compare(
636 currentPosition, separator.size(), separator) == 0);
639 bool IsEndReached() {
return currentPosition >= expressionUtf32.size(); }
642 struct IdentifierAndLocation {
644 ExpressionParserLocation location;
647 IdentifierAndLocation ReadIdentifierName(
bool allowDeprecatedSpacesInName =
true) {
649 size_t startPosition = currentPosition;
650 while (currentPosition < expressionUtf32.size() &&
653 || (allowDeprecatedSpacesInName && expressionUtf32[currentPosition] ==
' '))) {
654 name += expressionUtf32[currentPosition];
661 if (!name.
empty() && IsWhitespace(name[name.
size() - 1])) {
662 size_t lastCharacterPos = name.
size() - 1;
663 while (lastCharacterPos < name.
size() &&
664 IsWhitespace(name[lastCharacterPos])) {
667 if ((lastCharacterPos + 1) < name.
size()) {
668 name.
erase(lastCharacterPos + 1);
672 IdentifierAndLocation identifierAndLocation{
676 ExpressionParserLocation(startPosition, startPosition + name.
size())};
677 return identifierAndLocation;
680 std::unique_ptr<TextNode> ReadText();
682 std::unique_ptr<NumberNode> ReadNumber(
size_t minusSignPosition = -1);
684 std::unique_ptr<EmptyNode> ReadUntilWhitespace() {
685 size_t startPosition = GetCurrentPosition();
687 while (currentPosition < expressionUtf32.size() &&
688 !IsWhitespace(expressionUtf32[currentPosition])) {
689 text += expressionUtf32[currentPosition];
693 auto node = gd::make_unique<EmptyNode>(text);
695 ExpressionParserLocation(startPosition, GetCurrentPosition());
699 std::unique_ptr<EmptyNode> ReadUntilEnd() {
700 size_t startPosition = GetCurrentPosition();
702 while (currentPosition < expressionUtf32.size()) {
703 text += expressionUtf32[currentPosition];
707 auto node = gd::make_unique<EmptyNode>(text);
709 ExpressionParserLocation(startPosition, GetCurrentPosition());
713 size_t GetCurrentPosition() {
return currentPosition; }
715 gd::String::value_type GetCurrentChar() {
716 if (currentPosition < expressionUtf32.size()) {
717 return expressionUtf32[currentPosition];
729 std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
731 return std::move(gd::make_unique<ExpressionParserError>(
732 gd::ExpressionParserError::ErrorType::SyntaxError, message,
733 GetCurrentPosition()));
736 std::unique_ptr<ExpressionParserError> RaiseTypeError(
737 const gd::String &message,
size_t beginningPosition) {
738 return std::move(gd::make_unique<ExpressionParserError>(
739 gd::ExpressionParserError::ErrorType::MismatchedType, message,
740 beginningPosition, GetCurrentPosition()));
747 std::u32string expressionUtf32;
748 std::size_t currentPosition;
Class representing an expression used as a parameter of a gd::Instruction. This class is nothing more...
Definition: Expression.h:30
Parse an expression, returning a tree of node corresponding to the parsed expression.
Definition: ExpressionParser2.h:44
static size_t WrittenParametersFirstIndex(const gd::String &objectName, const gd::String &behaviorName)
Definition: ExpressionParser2.h:80
std::unique_ptr< ExpressionNode > ParseExpression(const gd::String &expression)
Definition: ExpressionParser2.h:56
String represents an UTF8 encoded string.
Definition: String.h:33
std::u32string ToUTF32() const
Definition: String.cpp:154
bool empty() const
Returns true if the string is empty.
Definition: String.h:157
iterator erase(iterator first, iterator last)
Erase the characters between first and last (last not included).
Definition: String.cpp:333
size_type size() const
Returns the string's length.
Definition: String.cpp:63
Definition: GrammarTerminals.h:9
bool IsAllowedInIdentifier(gd::String::value_type character)
Definition: GrammarTerminals.h:103
Definition: CommonTools.h:24
Definition: ExpressionParser2Node.h:25