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;
58 expression = expression_;
77 return !behaviorName.
empty() ? 2 : (!objectName.
empty() ? 1 : 0);
85 std::unique_ptr<ExpressionNode> Start() {
86 size_t expressionStartPosition = GetCurrentPosition();
90 if (!IsEndReached()) {
91 auto op = gd::make_unique<OperatorNode>(
' ');
92 op->leftHandSide = std::move(expression);
93 op->rightHandSide = ReadUntilEnd();
94 op->rightHandSide->parent = op.get();
96 op->rightHandSide->diagnostic = RaiseSyntaxError(
97 _(
"The expression has extra character at the end that should be "
98 "removed (or completed if your expression is not finished)."));
101 GetCurrentPosition());
102 return std::move(op);
108 std::unique_ptr<ExpressionNode> Expression() {
109 SkipAllWhitespaces();
111 size_t expressionStartPosition = GetCurrentPosition();
112 std::unique_ptr<ExpressionNode> leftHandSide = Term();
114 SkipAllWhitespaces();
116 if (IsEndReached())
return leftHandSide;
117 if (CheckIfChar(IsExpressionEndingChar))
return leftHandSide;
118 if (CheckIfChar(IsExpressionOperator)) {
119 auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
120 op->leftHandSide = std::move(leftHandSide);
121 op->leftHandSide->parent = op.get();
122 op->diagnostic = ValidateOperator(GetCurrentChar());
124 op->rightHandSide = Expression();
125 op->rightHandSide->parent = op.get();
127 op->location = ExpressionParserLocation(expressionStartPosition,
128 GetCurrentPosition());
129 return std::move(op);
132 leftHandSide->diagnostic = RaiseSyntaxError(
133 "More than one term was found. Verify that your expression is "
134 "properly written.");
136 auto op = gd::make_unique<OperatorNode>(
' ');
137 op->leftHandSide = std::move(leftHandSide);
138 op->leftHandSide->parent = op.get();
139 op->rightHandSide = Expression();
140 op->rightHandSide->parent = op.get();
142 ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
143 return std::move(op);
146 std::unique_ptr<ExpressionNode> Term() {
147 SkipAllWhitespaces();
149 size_t expressionStartPosition = GetCurrentPosition();
150 std::unique_ptr<ExpressionNode> factor = Factor();
152 SkipAllWhitespaces();
157 while (CheckIfChar(IsTermOperator)) {
158 auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
159 op->leftHandSide = std::move(factor);
160 op->leftHandSide->parent = op.get();
161 op->diagnostic = ValidateOperator(GetCurrentChar());
163 op->rightHandSide = Factor();
164 op->rightHandSide->parent = op.get();
165 op->location = ExpressionParserLocation(expressionStartPosition,
166 GetCurrentPosition());
167 SkipAllWhitespaces();
169 factor = std::move(op);
175 std::unique_ptr<ExpressionNode> Factor() {
176 SkipAllWhitespaces();
177 size_t expressionStartPosition = GetCurrentPosition();
179 if (CheckIfChar(IsQuote)) {
180 std::unique_ptr<ExpressionNode> factor = ReadText();
182 }
else if (CheckIfChar(IsUnaryOperator)) {
183 auto unaryOperatorCharacter = GetCurrentChar();
186 auto operatorOperand = Factor();
188 auto unaryOperator = gd::make_unique<UnaryOperatorNode>(
189 unaryOperatorCharacter);
190 unaryOperator->diagnostic = ValidateUnaryOperator(
191 unaryOperatorCharacter, expressionStartPosition);
192 unaryOperator->factor = std::move(operatorOperand);
193 unaryOperator->factor->parent = unaryOperator.get();
194 unaryOperator->location = ExpressionParserLocation(
195 expressionStartPosition, GetCurrentPosition());
197 return std::move(unaryOperator);
198 }
else if (CheckIfChar(IsNumberFirstChar)) {
199 std::unique_ptr<ExpressionNode> factor = ReadNumber();
201 }
else if (CheckIfChar(IsOpeningParenthesis)) {
202 size_t expressionStartPosition = GetCurrentPosition();
206 auto expression = Expression();
209 auto factor = gd::make_unique<SubExpressionNode>(std::move(expression));
211 if (!CheckIfChar(IsClosingParenthesis)) {
213 RaiseSyntaxError(_(
"Missing a closing parenthesis. Add a closing "
214 "parenthesis for each opening parenthesis."));
216 SkipIfChar(IsClosingParenthesis);
217 factor->location = ExpressionParserLocation(expressionStartPosition,
218 GetCurrentPosition());
220 return std::move(factor);
225 std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace();
229 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
231 auto identifierAndLocation = ReadIdentifierName();
233 auto nameLocation = identifierAndLocation.location;
235 SkipAllWhitespaces();
242 if (IsNamespaceSeparator()) {
243 SkipNamespaceSeparator();
244 SkipAllWhitespaces();
246 auto postNamespaceIdentifierAndLocation = ReadIdentifierName();
247 name += NAMESPACE_SEPARATOR;
248 name += postNamespaceIdentifierAndLocation.name;
249 ExpressionParserLocation completeNameLocation(
250 nameLocation.GetStartPosition(),
251 postNamespaceIdentifierAndLocation.location.GetEndPosition());
252 nameLocation = completeNameLocation;
255 if (CheckIfChar(IsOpeningParenthesis)) {
256 ExpressionParserLocation openingParenthesisLocation = SkipChar();
257 return FreeFunction(name, nameLocation, openingParenthesisLocation);
258 }
else if (CheckIfChar(IsDot)) {
259 ExpressionParserLocation dotLocation = SkipChar();
260 SkipAllWhitespaces();
261 return ObjectFunctionOrBehaviorFunctionOrVariable(
262 name, nameLocation, dotLocation);
263 }
else if (CheckIfChar(IsOpeningSquareBracket)) {
264 return Variable(name, nameLocation);
266 auto identifier = gd::make_unique<IdentifierNode>(name);
267 identifier->location = ExpressionParserLocation(
268 nameLocation.GetStartPosition(), GetCurrentPosition());
269 identifier->identifierNameLocation = identifier->location;
270 return std::move(identifier);
275 auto variable = gd::make_unique<VariableNode>(name);
277 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
278 variable->child = VariableAccessorOrVariableBracketAccessor();
279 variable->child->parent = variable.get();
282 variable->location = ExpressionParserLocation(
283 nameLocation.GetStartPosition(), GetCurrentPosition());
284 variable->nameLocation = nameLocation;
285 return std::move(variable);
288 std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
289 VariableAccessorOrVariableBracketAccessor() {
290 size_t childStartPosition = GetCurrentPosition();
292 SkipAllWhitespaces();
293 if (CheckIfChar(IsOpeningSquareBracket)) {
295 auto child = gd::make_unique<VariableBracketAccessorNode>(Expression());
296 child->expression->parent = child.get();
298 if (!CheckIfChar(IsClosingSquareBracket)) {
300 RaiseSyntaxError(_(
"Missing a closing bracket. Add a closing "
301 "bracket for each opening bracket."));
303 SkipIfChar(IsClosingSquareBracket);
305 SkipAllWhitespaces();
306 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
307 child->child = VariableAccessorOrVariableBracketAccessor();
308 child->child->parent = child.get();
311 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
313 return std::move(child);
314 }
else if (CheckIfChar(IsDot)) {
315 auto dotLocation = SkipChar();
316 SkipAllWhitespaces();
318 auto identifierAndLocation = ReadIdentifierName(
false);
320 gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
321 if (identifierAndLocation.name.empty()) {
322 child->diagnostic = RaiseSyntaxError(_(
"A name should be entered after the dot."));
325 SkipAllWhitespaces();
326 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
327 child->child = VariableAccessorOrVariableBracketAccessor();
328 child->child->parent = child.get();
330 child->nameLocation = identifierAndLocation.location;
331 child->dotLocation = dotLocation;
333 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
335 return std::move(child);
340 auto unrecognisedNode = gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>();
341 unrecognisedNode->diagnostic = RaiseSyntaxError(_(
"A dot or bracket was expected here."));
342 return std::move(unrecognisedNode);
345 std::unique_ptr<FunctionCallNode> FreeFunction(
347 const ExpressionParserLocation &identifierLocation,
348 const ExpressionParserLocation &openingParenthesisLocation) {
353 gd::make_unique<FunctionCallNode>(functionFullName);
354 auto parametersNode = Parameters(
function.get());
355 function->parameters = std::move(parametersNode.parameters);
356 function->diagnostic = std::move(parametersNode.diagnostic);
358 function->location = ExpressionParserLocation(
359 identifierLocation.GetStartPosition(), GetCurrentPosition());
360 function->functionNameLocation = identifierLocation;
361 function->openingParenthesisLocation = openingParenthesisLocation;
362 function->closingParenthesisLocation =
363 parametersNode.closingParenthesisLocation;
365 return std::move(
function);
368 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
369 ObjectFunctionOrBehaviorFunctionOrVariable(
371 const ExpressionParserLocation &parentIdentifierLocation,
372 const ExpressionParserLocation &parentIdentifierDotLocation) {
373 auto childIdentifierAndLocation = ReadIdentifierName(
false);
374 const gd::String &childIdentifierName = childIdentifierAndLocation.name;
375 const auto &childIdentifierNameLocation =
376 childIdentifierAndLocation.location;
378 std::unique_ptr<gd::ExpressionParserError> emptyNameError = childIdentifierName.
empty() ?
379 RaiseSyntaxError(_(
"A name should be entered after the dot.")) : nullptr;
381 SkipAllWhitespaces();
383 if (IsNamespaceSeparator()) {
384 ExpressionParserLocation namespaceSeparatorLocation =
385 SkipNamespaceSeparator();
386 SkipAllWhitespaces();
387 auto behaviorFunction = BehaviorFunction(parentIdentifier,
389 parentIdentifierLocation,
390 parentIdentifierDotLocation,
391 childIdentifierNameLocation,
392 namespaceSeparatorLocation);
394 if (emptyNameError) behaviorFunction->diagnostic = std::move(emptyNameError);
395 return std::move(behaviorFunction);
396 }
else if (CheckIfChar(IsOpeningParenthesis)) {
397 ExpressionParserLocation openingParenthesisLocation = SkipChar();
399 auto function = gd::make_unique<FunctionCallNode>(
401 childIdentifierName);
402 auto parametersNode = Parameters(
function.get(), parentIdentifier);
403 function->parameters = std::move(parametersNode.parameters),
404 function->diagnostic = emptyNameError ? std::move(emptyNameError) : std::move(parametersNode.diagnostic);
406 function->location = ExpressionParserLocation(
407 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
408 function->objectNameLocation = parentIdentifierLocation;
409 function->objectNameDotLocation = parentIdentifierDotLocation;
410 function->functionNameLocation = childIdentifierNameLocation;
411 function->openingParenthesisLocation = openingParenthesisLocation;
412 function->closingParenthesisLocation =
413 parametersNode.closingParenthesisLocation;
414 return std::move(
function);
415 }
else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
416 auto variable = gd::make_unique<VariableNode>(parentIdentifier);
417 variable->diagnostic = std::move(emptyNameError);
420 gd::make_unique<VariableAccessorNode>(childIdentifierName);
421 child->child = VariableAccessorOrVariableBracketAccessor();
422 child->child->parent = child.get();
423 child->nameLocation = childIdentifierNameLocation;
424 child->dotLocation = parentIdentifierDotLocation;
425 child->location = ExpressionParserLocation(
426 parentIdentifierDotLocation.GetStartPosition(), GetCurrentPosition());
427 variable->child = std::move(child);
428 variable->child->parent = variable.get();
430 variable->location = ExpressionParserLocation(
431 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
432 variable->nameLocation = parentIdentifierLocation;
434 return std::move(variable);
437 auto node = gd::make_unique<IdentifierNode>(
438 parentIdentifier, childIdentifierName);
439 node->location = ExpressionParserLocation(
440 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
441 node->identifierNameLocation = parentIdentifierLocation;
442 node->identifierNameDotLocation = parentIdentifierDotLocation;
443 node->childIdentifierNameLocation = childIdentifierNameLocation;
444 node->diagnostic = std::move(emptyNameError);
445 return std::move(node);
448 std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction(
451 const ExpressionParserLocation &objectNameLocation,
452 const ExpressionParserLocation &objectNameDotLocation,
453 const ExpressionParserLocation &behaviorNameLocation,
454 const ExpressionParserLocation &behaviorNameNamespaceSeparatorLocation) {
455 auto identifierAndLocation = ReadIdentifierName();
456 const gd::String &functionName = identifierAndLocation.name;
457 const auto &functionNameLocation = identifierAndLocation.location;
459 SkipAllWhitespaces();
461 if (CheckIfChar(IsOpeningParenthesis)) {
462 ExpressionParserLocation openingParenthesisLocation = SkipChar();
464 auto function = gd::make_unique<FunctionCallNode>(
468 auto parametersNode =
469 Parameters(
function.get(), objectName, behaviorName);
470 function->parameters = std::move(parametersNode.parameters);
471 function->diagnostic = std::move(parametersNode.diagnostic);
473 function->location = ExpressionParserLocation(
474 objectNameLocation.GetStartPosition(), GetCurrentPosition());
475 function->objectNameLocation = objectNameLocation;
476 function->objectNameDotLocation = objectNameDotLocation;
477 function->behaviorNameLocation = behaviorNameLocation;
478 function->behaviorNameNamespaceSeparatorLocation =
479 behaviorNameNamespaceSeparatorLocation;
480 function->openingParenthesisLocation = openingParenthesisLocation;
481 function->closingParenthesisLocation =
482 parametersNode.closingParenthesisLocation;
483 function->functionNameLocation = functionNameLocation;
484 return std::move(
function);
486 auto node = gd::make_unique<ObjectFunctionNameNode>(
487 objectName, behaviorName, functionName);
488 node->diagnostic = RaiseSyntaxError(
489 _(
"An opening parenthesis was expected here to call a function."));
491 node->location = ExpressionParserLocation(
492 objectNameLocation.GetStartPosition(), GetCurrentPosition());
493 node->objectNameLocation = objectNameLocation;
494 node->objectNameDotLocation = objectNameDotLocation;
495 node->objectFunctionOrBehaviorNameLocation = behaviorNameLocation;
496 node->behaviorNameNamespaceSeparatorLocation =
497 behaviorNameNamespaceSeparatorLocation;
498 node->behaviorFunctionNameLocation = functionNameLocation;
499 return std::move(node);
504 struct ParametersNode {
505 std::vector<std::unique_ptr<ExpressionNode>> parameters;
506 std::unique_ptr<gd::ExpressionParserError> diagnostic;
507 ExpressionParserLocation closingParenthesisLocation;
510 ParametersNode Parameters(
511 FunctionCallNode *functionCallNode,
514 std::vector<std::unique_ptr<ExpressionNode>> parameters;
517 bool previousCharacterIsParameterSeparator =
false;
518 while (!IsEndReached()) {
519 SkipAllWhitespaces();
521 if (CheckIfChar(IsClosingParenthesis) && !previousCharacterIsParameterSeparator) {
522 auto closingParenthesisLocation = SkipChar();
523 return ParametersNode{
524 std::move(parameters),
nullptr, closingParenthesisLocation};
526 bool isEmptyParameter = CheckIfChar(IsParameterSeparator)
527 || (CheckIfChar(IsClosingParenthesis) && previousCharacterIsParameterSeparator);
528 auto parameter = isEmptyParameter ? gd::make_unique<EmptyNode>() : Expression();
529 parameter->parent = functionCallNode;
530 parameters.push_back(std::move(parameter));
532 SkipAllWhitespaces();
533 previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
534 SkipIfChar(IsParameterSeparator);
537 ExpressionParserLocation invalidClosingParenthesisLocation;
538 return ParametersNode{
539 std::move(parameters),
540 RaiseSyntaxError(_(
"The list of parameters is not terminated. Add a "
541 "closing parenthesis to end the parameters.")),
542 invalidClosingParenthesisLocation};
546 std::unique_ptr<ExpressionParserError> ValidateOperator(
547 gd::String::value_type operatorChar) {
548 if (operatorChar ==
'+' || operatorChar ==
'-' || operatorChar ==
'/' ||
549 operatorChar ==
'*') {
550 return std::unique_ptr<ExpressionParserError>(
nullptr);
552 return gd::make_unique<ExpressionParserError>(
553 gd::ExpressionParserError::ErrorType::InvalidOperator,
554 _(
"You've used an operator that is not supported. Operator should be "
555 "either +, -, / or *."),
556 GetCurrentPosition());
559 std::unique_ptr<ExpressionParserError> ValidateUnaryOperator(
560 gd::String::value_type operatorChar,
562 if (operatorChar ==
'+' || operatorChar ==
'-') {
563 return std::unique_ptr<ExpressionParserError>(
nullptr);
566 return gd::make_unique<ExpressionParserError>(
567 gd::ExpressionParserError::ErrorType::InvalidOperator,
568 _(
"You've used an \"unary\" operator that is not supported. Operator "
579 ExpressionParserLocation SkipChar() {
580 size_t startPosition = currentPosition;
581 return ExpressionParserLocation(startPosition, ++currentPosition);
584 void SkipAllWhitespaces() {
585 while (currentPosition < expression.size() &&
586 IsWhitespace(expression[currentPosition])) {
592 const std::function<
bool(gd::String::value_type)> &predicate) {
593 if (CheckIfChar(predicate)) {
598 ExpressionParserLocation SkipNamespaceSeparator() {
599 size_t startPosition = currentPosition;
602 if (IsNamespaceSeparator()) {
603 currentPosition += NAMESPACE_SEPARATOR.size();
606 return ExpressionParserLocation(startPosition, currentPosition);
610 const std::function<
bool(gd::String::value_type)> &predicate) {
611 if (currentPosition >= expression.size())
return false;
612 gd::String::value_type character = expression[currentPosition];
614 return predicate(character);
617 bool IsNamespaceSeparator() {
620 return (currentPosition + NAMESPACE_SEPARATOR.size() <= expression.size() &&
621 expression.substr(currentPosition, NAMESPACE_SEPARATOR.size()) ==
622 NAMESPACE_SEPARATOR);
625 bool IsEndReached() {
return currentPosition >= expression.size(); }
628 struct IdentifierAndLocation {
630 ExpressionParserLocation location;
633 IdentifierAndLocation ReadIdentifierName(
bool allowDeprecatedSpacesInName =
true) {
635 size_t startPosition = currentPosition;
636 while (currentPosition < expression.size() &&
639 || (allowDeprecatedSpacesInName && expression[currentPosition] ==
' '))) {
640 name += expression[currentPosition];
647 if (!name.
empty() && IsWhitespace(name[name.
size() - 1])) {
648 size_t lastCharacterPos = name.
size() - 1;
649 while (lastCharacterPos < name.
size() &&
650 IsWhitespace(name[lastCharacterPos])) {
653 if ((lastCharacterPos + 1) < name.
size()) {
654 name.
erase(lastCharacterPos + 1);
658 IdentifierAndLocation identifierAndLocation{
662 ExpressionParserLocation(startPosition, startPosition + name.
size())};
663 return identifierAndLocation;
666 std::unique_ptr<TextNode> ReadText();
668 std::unique_ptr<NumberNode> ReadNumber();
670 std::unique_ptr<EmptyNode> ReadUntilWhitespace() {
671 size_t startPosition = GetCurrentPosition();
673 while (currentPosition < expression.size() &&
674 !IsWhitespace(expression[currentPosition])) {
675 text += expression[currentPosition];
679 auto node = gd::make_unique<EmptyNode>(text);
681 ExpressionParserLocation(startPosition, GetCurrentPosition());
685 std::unique_ptr<EmptyNode> ReadUntilEnd() {
686 size_t startPosition = GetCurrentPosition();
688 while (currentPosition < expression.size()) {
689 text += expression[currentPosition];
693 auto node = gd::make_unique<EmptyNode>(text);
695 ExpressionParserLocation(startPosition, GetCurrentPosition());
699 size_t GetCurrentPosition() {
return currentPosition; }
701 gd::String::value_type GetCurrentChar() {
702 if (currentPosition < expression.size()) {
703 return expression[currentPosition];
715 std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
717 return std::move(gd::make_unique<ExpressionParserError>(
718 gd::ExpressionParserError::ErrorType::SyntaxError, message,
719 GetCurrentPosition()));
722 std::unique_ptr<ExpressionParserError> RaiseTypeError(
723 const gd::String &message,
size_t beginningPosition) {
724 return std::move(gd::make_unique<ExpressionParserError>(
725 gd::ExpressionParserError::ErrorType::MismatchedType, message,
726 beginningPosition, GetCurrentPosition()));
731 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:73
std::unique_ptr< ExpressionNode > ParseExpression(const gd::String &expression_)
Definition: ExpressionParser2.h:56
String represents an UTF8 encoded string.
Definition: String.h:33
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:330
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:99
Definition: CommonTools.h:24
Definition: ExpressionParser2Node.h:25