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)) {
203 std::unique_ptr<ExpressionNode> factor = SubExpression();
205 if (!CheckIfChar(IsClosingParenthesis)) {
207 RaiseSyntaxError(_(
"Missing a closing parenthesis. Add a closing "
208 "parenthesis for each opening parenthesis."));
210 SkipIfChar(IsClosingParenthesis);
216 std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace();
220 std::unique_ptr<SubExpressionNode> SubExpression() {
221 size_t expressionStartPosition = GetCurrentPosition();
223 auto expression = Expression();
226 gd::make_unique<SubExpressionNode>(std::move(expression));
227 subExpression->location =
228 ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
230 return std::move(subExpression);
233 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
235 auto identifierAndLocation = ReadIdentifierName();
237 auto nameLocation = identifierAndLocation.location;
239 SkipAllWhitespaces();
246 if (IsNamespaceSeparator()) {
247 SkipNamespaceSeparator();
248 SkipAllWhitespaces();
250 auto postNamespaceIdentifierAndLocation = ReadIdentifierName();
251 name += NAMESPACE_SEPARATOR;
252 name += postNamespaceIdentifierAndLocation.name;
253 ExpressionParserLocation completeNameLocation(
254 nameLocation.GetStartPosition(),
255 postNamespaceIdentifierAndLocation.location.GetEndPosition());
256 nameLocation = completeNameLocation;
259 if (CheckIfChar(IsOpeningParenthesis)) {
260 ExpressionParserLocation openingParenthesisLocation = SkipChar();
261 return FreeFunction(name, nameLocation, openingParenthesisLocation);
262 }
else if (CheckIfChar(IsDot)) {
263 ExpressionParserLocation dotLocation = SkipChar();
264 SkipAllWhitespaces();
265 return ObjectFunctionOrBehaviorFunctionOrVariable(
266 name, nameLocation, dotLocation);
267 }
else if (CheckIfChar(IsOpeningSquareBracket)) {
268 return Variable(name, nameLocation);
270 auto identifier = gd::make_unique<IdentifierNode>(name);
271 identifier->location = ExpressionParserLocation(
272 nameLocation.GetStartPosition(), GetCurrentPosition());
273 identifier->identifierNameLocation = identifier->location;
274 return std::move(identifier);
279 auto variable = gd::make_unique<VariableNode>(name);
281 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
282 variable->child = VariableAccessorOrVariableBracketAccessor();
283 variable->child->parent = variable.get();
286 variable->location = ExpressionParserLocation(
287 nameLocation.GetStartPosition(), GetCurrentPosition());
288 variable->nameLocation = nameLocation;
289 return std::move(variable);
292 std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
293 VariableAccessorOrVariableBracketAccessor() {
294 size_t childStartPosition = GetCurrentPosition();
296 SkipAllWhitespaces();
297 if (CheckIfChar(IsOpeningSquareBracket)) {
299 auto child = gd::make_unique<VariableBracketAccessorNode>(Expression());
300 child->expression->parent = child.get();
302 if (!CheckIfChar(IsClosingSquareBracket)) {
304 RaiseSyntaxError(_(
"Missing a closing bracket. Add a closing "
305 "bracket for each opening bracket."));
307 SkipIfChar(IsClosingSquareBracket);
309 SkipAllWhitespaces();
310 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
311 child->child = VariableAccessorOrVariableBracketAccessor();
312 child->child->parent = child.get();
315 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
317 return std::move(child);
318 }
else if (CheckIfChar(IsDot)) {
319 auto dotLocation = SkipChar();
320 SkipAllWhitespaces();
322 auto identifierAndLocation = ReadIdentifierName(
false);
324 gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
325 if (identifierAndLocation.name.empty()) {
326 child->diagnostic = RaiseSyntaxError(_(
"A name should be entered after the dot."));
329 SkipAllWhitespaces();
330 if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
331 child->child = VariableAccessorOrVariableBracketAccessor();
332 child->child->parent = child.get();
334 child->nameLocation = identifierAndLocation.location;
335 child->dotLocation = dotLocation;
337 ExpressionParserLocation(childStartPosition, GetCurrentPosition());
339 return std::move(child);
344 auto unrecognisedNode = gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>();
345 unrecognisedNode->diagnostic = RaiseSyntaxError(_(
"A dot or bracket was expected here."));
346 return std::move(unrecognisedNode);
349 std::unique_ptr<FunctionCallNode> FreeFunction(
351 const ExpressionParserLocation &identifierLocation,
352 const ExpressionParserLocation &openingParenthesisLocation) {
357 gd::make_unique<FunctionCallNode>(functionFullName);
358 auto parametersNode = Parameters(
function.get());
359 function->parameters = std::move(parametersNode.parameters);
360 function->diagnostic = std::move(parametersNode.diagnostic);
362 function->location = ExpressionParserLocation(
363 identifierLocation.GetStartPosition(), GetCurrentPosition());
364 function->functionNameLocation = identifierLocation;
365 function->openingParenthesisLocation = openingParenthesisLocation;
366 function->closingParenthesisLocation =
367 parametersNode.closingParenthesisLocation;
369 return std::move(
function);
372 std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
373 ObjectFunctionOrBehaviorFunctionOrVariable(
375 const ExpressionParserLocation &parentIdentifierLocation,
376 const ExpressionParserLocation &parentIdentifierDotLocation) {
377 auto childIdentifierAndLocation = ReadIdentifierName(
false);
378 const gd::String &childIdentifierName = childIdentifierAndLocation.name;
379 const auto &childIdentifierNameLocation =
380 childIdentifierAndLocation.location;
382 std::unique_ptr<gd::ExpressionParserError> emptyNameError = childIdentifierName.
empty() ?
383 RaiseSyntaxError(_(
"A name should be entered after the dot.")) : nullptr;
385 SkipAllWhitespaces();
387 if (IsNamespaceSeparator()) {
388 ExpressionParserLocation namespaceSeparatorLocation =
389 SkipNamespaceSeparator();
390 SkipAllWhitespaces();
391 auto behaviorFunction = BehaviorFunction(parentIdentifier,
393 parentIdentifierLocation,
394 parentIdentifierDotLocation,
395 childIdentifierNameLocation,
396 namespaceSeparatorLocation);
398 if (emptyNameError) behaviorFunction->diagnostic = std::move(emptyNameError);
399 return std::move(behaviorFunction);
400 }
else if (CheckIfChar(IsOpeningParenthesis)) {
401 ExpressionParserLocation openingParenthesisLocation = SkipChar();
403 auto function = gd::make_unique<FunctionCallNode>(
405 childIdentifierName);
406 auto parametersNode = Parameters(
function.get(), parentIdentifier);
407 function->parameters = std::move(parametersNode.parameters),
408 function->diagnostic = emptyNameError ? std::move(emptyNameError) : std::move(parametersNode.diagnostic);
410 function->location = ExpressionParserLocation(
411 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
412 function->objectNameLocation = parentIdentifierLocation;
413 function->objectNameDotLocation = parentIdentifierDotLocation;
414 function->functionNameLocation = childIdentifierNameLocation;
415 function->openingParenthesisLocation = openingParenthesisLocation;
416 function->closingParenthesisLocation =
417 parametersNode.closingParenthesisLocation;
418 return std::move(
function);
419 }
else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
420 auto variable = gd::make_unique<VariableNode>(parentIdentifier);
421 variable->diagnostic = std::move(emptyNameError);
424 gd::make_unique<VariableAccessorNode>(childIdentifierName);
425 child->child = VariableAccessorOrVariableBracketAccessor();
426 child->child->parent = child.get();
427 child->nameLocation = childIdentifierNameLocation;
428 child->dotLocation = parentIdentifierDotLocation;
429 child->location = ExpressionParserLocation(
430 parentIdentifierDotLocation.GetStartPosition(), GetCurrentPosition());
431 variable->child = std::move(child);
432 variable->child->parent = variable.get();
434 variable->location = ExpressionParserLocation(
435 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
436 variable->nameLocation = parentIdentifierLocation;
438 return std::move(variable);
441 auto node = gd::make_unique<IdentifierNode>(
442 parentIdentifier, childIdentifierName);
443 node->location = ExpressionParserLocation(
444 parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
445 node->identifierNameLocation = parentIdentifierLocation;
446 node->identifierNameDotLocation = parentIdentifierDotLocation;
447 node->childIdentifierNameLocation = childIdentifierNameLocation;
448 node->diagnostic = std::move(emptyNameError);
449 return std::move(node);
452 std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction(
455 const ExpressionParserLocation &objectNameLocation,
456 const ExpressionParserLocation &objectNameDotLocation,
457 const ExpressionParserLocation &behaviorNameLocation,
458 const ExpressionParserLocation &behaviorNameNamespaceSeparatorLocation) {
459 auto identifierAndLocation = ReadIdentifierName();
460 const gd::String &functionName = identifierAndLocation.name;
461 const auto &functionNameLocation = identifierAndLocation.location;
463 SkipAllWhitespaces();
465 if (CheckIfChar(IsOpeningParenthesis)) {
466 ExpressionParserLocation openingParenthesisLocation = SkipChar();
468 auto function = gd::make_unique<FunctionCallNode>(
472 auto parametersNode =
473 Parameters(
function.get(), objectName, behaviorName);
474 function->parameters = std::move(parametersNode.parameters);
475 function->diagnostic = std::move(parametersNode.diagnostic);
477 function->location = ExpressionParserLocation(
478 objectNameLocation.GetStartPosition(), GetCurrentPosition());
479 function->objectNameLocation = objectNameLocation;
480 function->objectNameDotLocation = objectNameDotLocation;
481 function->behaviorNameLocation = behaviorNameLocation;
482 function->behaviorNameNamespaceSeparatorLocation =
483 behaviorNameNamespaceSeparatorLocation;
484 function->openingParenthesisLocation = openingParenthesisLocation;
485 function->closingParenthesisLocation =
486 parametersNode.closingParenthesisLocation;
487 function->functionNameLocation = functionNameLocation;
488 return std::move(
function);
490 auto node = gd::make_unique<ObjectFunctionNameNode>(
491 objectName, behaviorName, functionName);
492 node->diagnostic = RaiseSyntaxError(
493 _(
"An opening parenthesis was expected here to call a function."));
495 node->location = ExpressionParserLocation(
496 objectNameLocation.GetStartPosition(), GetCurrentPosition());
497 node->objectNameLocation = objectNameLocation;
498 node->objectNameDotLocation = objectNameDotLocation;
499 node->objectFunctionOrBehaviorNameLocation = behaviorNameLocation;
500 node->behaviorNameNamespaceSeparatorLocation =
501 behaviorNameNamespaceSeparatorLocation;
502 node->behaviorFunctionNameLocation = functionNameLocation;
503 return std::move(node);
508 struct ParametersNode {
509 std::vector<std::unique_ptr<ExpressionNode>> parameters;
510 std::unique_ptr<gd::ExpressionParserError> diagnostic;
511 ExpressionParserLocation closingParenthesisLocation;
514 ParametersNode Parameters(
515 FunctionCallNode *functionCallNode,
518 std::vector<std::unique_ptr<ExpressionNode>> parameters;
521 bool previousCharacterIsParameterSeparator =
false;
522 while (!IsEndReached()) {
523 SkipAllWhitespaces();
525 if (CheckIfChar(IsClosingParenthesis) && !previousCharacterIsParameterSeparator) {
526 auto closingParenthesisLocation = SkipChar();
527 return ParametersNode{
528 std::move(parameters),
nullptr, closingParenthesisLocation};
530 bool isEmptyParameter = CheckIfChar(IsParameterSeparator)
531 || (CheckIfChar(IsClosingParenthesis) && previousCharacterIsParameterSeparator);
532 auto parameter = isEmptyParameter ? gd::make_unique<EmptyNode>() : Expression();
533 parameter->parent = functionCallNode;
534 parameters.push_back(std::move(parameter));
536 SkipAllWhitespaces();
537 previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
538 SkipIfChar(IsParameterSeparator);
541 ExpressionParserLocation invalidClosingParenthesisLocation;
542 return ParametersNode{
543 std::move(parameters),
544 RaiseSyntaxError(_(
"The list of parameters is not terminated. Add a "
545 "closing parenthesis to end the parameters.")),
546 invalidClosingParenthesisLocation};
550 std::unique_ptr<ExpressionParserError> ValidateOperator(
551 gd::String::value_type operatorChar) {
552 if (operatorChar ==
'+' || operatorChar ==
'-' || operatorChar ==
'/' ||
553 operatorChar ==
'*') {
554 return std::unique_ptr<ExpressionParserError>(
nullptr);
556 return gd::make_unique<ExpressionParserError>(
557 gd::ExpressionParserError::ErrorType::InvalidOperator,
558 _(
"You've used an operator that is not supported. Operator should be "
559 "either +, -, / or *."),
560 GetCurrentPosition());
563 std::unique_ptr<ExpressionParserError> ValidateUnaryOperator(
564 gd::String::value_type operatorChar,
566 if (operatorChar ==
'+' || operatorChar ==
'-') {
567 return std::unique_ptr<ExpressionParserError>(
nullptr);
570 return gd::make_unique<ExpressionParserError>(
571 gd::ExpressionParserError::ErrorType::InvalidOperator,
572 _(
"You've used an \"unary\" operator that is not supported. Operator "
583 ExpressionParserLocation SkipChar() {
584 size_t startPosition = currentPosition;
585 return ExpressionParserLocation(startPosition, ++currentPosition);
588 void SkipAllWhitespaces() {
589 while (currentPosition < expression.size() &&
590 IsWhitespace(expression[currentPosition])) {
596 const std::function<
bool(gd::String::value_type)> &predicate) {
597 if (CheckIfChar(predicate)) {
602 ExpressionParserLocation SkipNamespaceSeparator() {
603 size_t startPosition = currentPosition;
606 if (IsNamespaceSeparator()) {
607 currentPosition += NAMESPACE_SEPARATOR.size();
610 return ExpressionParserLocation(startPosition, currentPosition);
614 const std::function<
bool(gd::String::value_type)> &predicate) {
615 if (currentPosition >= expression.size())
return false;
616 gd::String::value_type character = expression[currentPosition];
618 return predicate(character);
621 bool IsNamespaceSeparator() {
624 return (currentPosition + NAMESPACE_SEPARATOR.size() <= expression.size() &&
625 expression.substr(currentPosition, NAMESPACE_SEPARATOR.size()) ==
626 NAMESPACE_SEPARATOR);
629 bool IsEndReached() {
return currentPosition >= expression.size(); }
632 struct IdentifierAndLocation {
634 ExpressionParserLocation location;
637 IdentifierAndLocation ReadIdentifierName(
bool allowDeprecatedSpacesInName =
true) {
639 size_t startPosition = currentPosition;
640 while (currentPosition < expression.size() &&
643 || (allowDeprecatedSpacesInName && expression[currentPosition] ==
' '))) {
644 name += expression[currentPosition];
651 if (!name.
empty() && IsWhitespace(name[name.
size() - 1])) {
652 size_t lastCharacterPos = name.
size() - 1;
653 while (lastCharacterPos < name.
size() &&
654 IsWhitespace(name[lastCharacterPos])) {
657 if ((lastCharacterPos + 1) < name.
size()) {
658 name.
erase(lastCharacterPos + 1);
662 IdentifierAndLocation identifierAndLocation{
666 ExpressionParserLocation(startPosition, startPosition + name.
size())};
667 return identifierAndLocation;
670 std::unique_ptr<TextNode> ReadText();
672 std::unique_ptr<NumberNode> ReadNumber();
674 std::unique_ptr<EmptyNode> ReadUntilWhitespace() {
675 size_t startPosition = GetCurrentPosition();
677 while (currentPosition < expression.size() &&
678 !IsWhitespace(expression[currentPosition])) {
679 text += expression[currentPosition];
683 auto node = gd::make_unique<EmptyNode>(text);
685 ExpressionParserLocation(startPosition, GetCurrentPosition());
689 std::unique_ptr<EmptyNode> ReadUntilEnd() {
690 size_t startPosition = GetCurrentPosition();
692 while (currentPosition < expression.size()) {
693 text += expression[currentPosition];
697 auto node = gd::make_unique<EmptyNode>(text);
699 ExpressionParserLocation(startPosition, GetCurrentPosition());
703 size_t GetCurrentPosition() {
return currentPosition; }
705 gd::String::value_type GetCurrentChar() {
706 if (currentPosition < expression.size()) {
707 return expression[currentPosition];
719 std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
721 return std::move(gd::make_unique<ExpressionParserError>(
722 gd::ExpressionParserError::ErrorType::SyntaxError, message,
723 GetCurrentPosition()));
726 std::unique_ptr<ExpressionParserError> RaiseTypeError(
727 const gd::String &message,
size_t beginningPosition) {
728 return std::move(gd::make_unique<ExpressionParserError>(
729 gd::ExpressionParserError::ErrorType::MismatchedType, message,
730 beginningPosition, GetCurrentPosition()));
735 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