mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
435 lines
16 KiB
C++
435 lines
16 KiB
C++
/*
|
|
* GDevelop Core
|
|
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
|
* reserved. This project is released under the MIT License.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "ExpressionParser2NodeWorker.h"
|
|
#include "GDCore/String.h"
|
|
|
|
namespace gd {
|
|
class Expression;
|
|
class ObjectsContainer;
|
|
class Platform;
|
|
class ParameterMetadata;
|
|
class ExpressionMetadata;
|
|
struct FunctionCallNode;
|
|
} // namespace gd
|
|
|
|
namespace gd {
|
|
|
|
struct GD_CORE_API ExpressionParserLocation {
|
|
ExpressionParserLocation() : isValid(false){};
|
|
ExpressionParserLocation(size_t position)
|
|
: isValid(true), startPosition(position), endPosition(position){};
|
|
ExpressionParserLocation(size_t startPosition_, size_t endPosition_)
|
|
: isValid(true),
|
|
startPosition(startPosition_),
|
|
endPosition(endPosition_){};
|
|
size_t GetStartPosition() const { return startPosition; }
|
|
size_t GetEndPosition() const { return endPosition; }
|
|
bool IsValid() const { return isValid; }
|
|
|
|
private:
|
|
bool isValid;
|
|
size_t startPosition = 0;
|
|
size_t endPosition = 0;
|
|
};
|
|
|
|
/**
|
|
* \brief An error that can be attached to a gd::ExpressionNode.
|
|
*/
|
|
struct GD_CORE_API ExpressionParserError {
|
|
enum ErrorType {
|
|
SyntaxError,
|
|
InvalidOperator,
|
|
MismatchedType,
|
|
UndeclaredVariable,
|
|
UnknownIdentifier,
|
|
BracketsNotAllowedForObjects,
|
|
TooFewParameters,
|
|
TooManyParameters,
|
|
InvalidFunctionName,
|
|
MalformedVariableParameter,
|
|
MalformedObjectParameter,
|
|
UnknownParameterType,
|
|
MissingBehavior,
|
|
VariableNameCollision,
|
|
};
|
|
|
|
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
|
const gd::String &message_,
|
|
const ExpressionParserLocation &location_,
|
|
const gd::String &actualValue_ = "",
|
|
const gd::String &objectName_ = "")
|
|
: type(type_), message(message_), location(location_),
|
|
actualValue(actualValue_), objectName(objectName_){};
|
|
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
|
const gd::String &message_, size_t position_)
|
|
: type(type_), message(message_), location(position_){};
|
|
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
|
const gd::String &message_, size_t startPosition_,
|
|
size_t endPosition_)
|
|
: type(type_), message(message_),
|
|
location(startPosition_, endPosition_){};
|
|
virtual ~ExpressionParserError(){};
|
|
|
|
gd::ExpressionParserError::ErrorType GetType() { return type; }
|
|
const gd::String &GetMessage() { return message; }
|
|
const gd::String &GetObjectName() { return objectName; }
|
|
const gd::String &GetActualValue() { return actualValue; }
|
|
size_t GetStartPosition() { return location.GetStartPosition(); }
|
|
size_t GetEndPosition() { return location.GetEndPosition(); }
|
|
|
|
private:
|
|
gd::ExpressionParserError::ErrorType type;
|
|
gd::String message;
|
|
ExpressionParserLocation location;
|
|
gd::String objectName;
|
|
gd::String actualValue;
|
|
};
|
|
|
|
/**
|
|
* \brief The base node, from which all nodes in the tree of
|
|
* an expression inherits from.
|
|
*/
|
|
struct GD_CORE_API ExpressionNode {
|
|
ExpressionNode() : parent(nullptr) {};
|
|
virtual ~ExpressionNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker){};
|
|
|
|
std::unique_ptr<ExpressionParserError> diagnostic;
|
|
ExpressionParserLocation location; ///< The location of the entire node. Some
|
|
/// nodes might have other locations
|
|
/// stored inside them. For example, a
|
|
/// function can store the position of the
|
|
/// object name, the dot, the function
|
|
/// name, etc...
|
|
ExpressionNode *parent;
|
|
};
|
|
|
|
struct GD_CORE_API SubExpressionNode : public ExpressionNode {
|
|
SubExpressionNode(std::unique_ptr<ExpressionNode> expression_)
|
|
: ExpressionNode(), expression(std::move(expression_)){};
|
|
virtual ~SubExpressionNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitSubExpressionNode(*this);
|
|
};
|
|
|
|
std::unique_ptr<ExpressionNode> expression;
|
|
};
|
|
|
|
/**
|
|
* \brief An operator node. For example: "lhs + rhs".
|
|
*/
|
|
struct GD_CORE_API OperatorNode : public ExpressionNode {
|
|
OperatorNode(gd::String::value_type op_)
|
|
: ExpressionNode(), op(op_){};
|
|
virtual ~OperatorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitOperatorNode(*this);
|
|
};
|
|
|
|
std::unique_ptr<ExpressionNode> leftHandSide;
|
|
std::unique_ptr<ExpressionNode> rightHandSide;
|
|
gd::String::value_type op;
|
|
};
|
|
|
|
/**
|
|
* \brief A unary operator node. For example: "-2".
|
|
*/
|
|
struct GD_CORE_API UnaryOperatorNode : public ExpressionNode {
|
|
UnaryOperatorNode(gd::String::value_type op_)
|
|
: ExpressionNode(), op(op_){};
|
|
virtual ~UnaryOperatorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitUnaryOperatorNode(*this);
|
|
};
|
|
|
|
std::unique_ptr<ExpressionNode> factor;
|
|
gd::String::value_type op;
|
|
};
|
|
|
|
/**
|
|
* \brief A number node. For example: "123".
|
|
* Its `type` is always "number".
|
|
*/
|
|
struct GD_CORE_API NumberNode : public ExpressionNode {
|
|
NumberNode(const gd::String &number_)
|
|
: ExpressionNode(), number(number_){};
|
|
virtual ~NumberNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitNumberNode(*this);
|
|
};
|
|
|
|
//
|
|
gd::String number;
|
|
};
|
|
|
|
/**
|
|
* \brief A text node. For example: "Hello World".
|
|
* Its `type` is always "string".
|
|
*/
|
|
struct GD_CORE_API TextNode : public ExpressionNode {
|
|
TextNode(const gd::String &text_) : ExpressionNode(), text(text_){};
|
|
virtual ~TextNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitTextNode(*this);
|
|
};
|
|
|
|
gd::String text;
|
|
};
|
|
|
|
struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
|
|
: public ExpressionNode {
|
|
IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode()
|
|
: ExpressionNode(){};
|
|
};
|
|
|
|
/**
|
|
* \brief An identifier node, usually representing an object or a variable
|
|
* with an optional function name or child variable name respectively.
|
|
*
|
|
* The name of a function to call on an object or the behavior,
|
|
* for example: "MyObject.Function" or "MyObject.Physics".
|
|
*
|
|
* A variable, potentially with accessor to its child,
|
|
* for example: MyVariable or MyVariable.MyChild
|
|
*/
|
|
struct GD_CORE_API IdentifierNode
|
|
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
IdentifierNode(
|
|
const gd::String &identifierName_)
|
|
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
identifierName(identifierName_),
|
|
childIdentifierName(""){};
|
|
IdentifierNode(
|
|
const gd::String &identifierName_,
|
|
const gd::String &childIdentifierName_)
|
|
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
identifierName(identifierName_),
|
|
childIdentifierName(childIdentifierName_){};
|
|
virtual ~IdentifierNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitIdentifierNode(*this);
|
|
};
|
|
|
|
gd::String identifierName; ///< The object or variable name.
|
|
gd::String childIdentifierName; ///< The object function or variable child name.
|
|
|
|
|
|
ExpressionParserLocation
|
|
identifierNameLocation; ///< Location of the object or variable name.
|
|
ExpressionParserLocation
|
|
identifierNameDotLocation; ///< Location of the "." after the object or variable name.
|
|
ExpressionParserLocation childIdentifierNameLocation; ///< Location of object
|
|
/// function, behavior or
|
|
/// child variable name.
|
|
};
|
|
|
|
struct GD_CORE_API FunctionCallOrObjectFunctionNameOrEmptyNode
|
|
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
FunctionCallOrObjectFunctionNameOrEmptyNode()
|
|
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(){};
|
|
virtual ~FunctionCallOrObjectFunctionNameOrEmptyNode(){};
|
|
void Visit(ExpressionParser2NodeWorker &worker) override{};
|
|
};
|
|
|
|
struct GD_CORE_API VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
|
|
VariableAccessorOrVariableBracketAccessorNode() : ExpressionNode(){};
|
|
|
|
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
|
|
};
|
|
|
|
/**
|
|
* \brief A variable, or object variable, with bracket accessor or at least 2 "dot" accessors.
|
|
*
|
|
* Example: `MyVariable["MyChildren"]` or `MyVariable.MyChildren.MyGrandChildren`.
|
|
* Example: `MyObject["MyVariable"]` or `MyObject.MyVariable.MyChildren`.
|
|
*
|
|
* Other cases like "MyVariable" or "MyVariable.MyChildren" are IdentifierNode
|
|
* to allow handling ambiguities.
|
|
*
|
|
* \see gd::IdentifierNode
|
|
* \see gd::VariableAccessorNode
|
|
* \see gd::VariableBracketAccessorNode
|
|
*/
|
|
struct GD_CORE_API VariableNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
VariableNode(const gd::String &name_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(), name(name_){};
|
|
virtual ~VariableNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableNode(*this);
|
|
};
|
|
|
|
gd::String name;
|
|
|
|
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
|
|
child; // Can be nullptr if no accessor
|
|
|
|
ExpressionParserLocation nameLocation;
|
|
};
|
|
|
|
/**
|
|
* \brief A direct accessor to a child variable. Example: MyChild
|
|
* in MyVariable.MyChild
|
|
*/
|
|
struct GD_CORE_API VariableAccessorNode
|
|
: public VariableAccessorOrVariableBracketAccessorNode {
|
|
VariableAccessorNode(const gd::String &name_)
|
|
: VariableAccessorOrVariableBracketAccessorNode(), name(name_){};
|
|
virtual ~VariableAccessorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableAccessorNode(*this);
|
|
};
|
|
|
|
gd::String name;
|
|
ExpressionParserLocation nameLocation;
|
|
ExpressionParserLocation dotLocation;
|
|
};
|
|
|
|
/**
|
|
* \brief A bracket accessor to a child variable. Example: ["MyChild"]
|
|
* (in MyVariable["MyChild"]).
|
|
*/
|
|
struct GD_CORE_API VariableBracketAccessorNode
|
|
: public VariableAccessorOrVariableBracketAccessorNode {
|
|
VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_)
|
|
: VariableAccessorOrVariableBracketAccessorNode(), expression(std::move(expression_)){};
|
|
virtual ~VariableBracketAccessorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableBracketAccessorNode(*this);
|
|
};
|
|
|
|
std::unique_ptr<ExpressionNode> expression;
|
|
};
|
|
|
|
/**
|
|
* \brief The name of a function to call on an object or the behavior
|
|
* For example: "MyObject.Physics::LinearVelocity".
|
|
*
|
|
* Other cases like "MyObject.Function" or "MyObject.Physics" are IdentifierNode
|
|
* to allow handling ambiguities.
|
|
*
|
|
* \see gd::IdentifierNode
|
|
*/
|
|
struct GD_CORE_API ObjectFunctionNameNode
|
|
: public FunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
ObjectFunctionNameNode(const gd::String &objectName_,
|
|
const gd::String &objectFunctionOrBehaviorName_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
objectName(objectName_),
|
|
objectFunctionOrBehaviorName(objectFunctionOrBehaviorName_) {}
|
|
ObjectFunctionNameNode(const gd::String &objectName_,
|
|
const gd::String &behaviorName_,
|
|
const gd::String &behaviorFunctionName_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
objectName(objectName_),
|
|
objectFunctionOrBehaviorName(behaviorName_),
|
|
behaviorFunctionName(behaviorFunctionName_) {}
|
|
virtual ~ObjectFunctionNameNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitObjectFunctionNameNode(*this);
|
|
};
|
|
|
|
gd::String objectName;
|
|
gd::String objectFunctionOrBehaviorName; ///< Behavior name if
|
|
///`behaviorFunctionName` is not
|
|
/// empty.
|
|
gd::String behaviorFunctionName; ///< If empty, then
|
|
/// objectFunctionOrBehaviorName is filled
|
|
/// with the behavior name.
|
|
|
|
ExpressionParserLocation
|
|
objectNameLocation; ///< Location of the object name.
|
|
ExpressionParserLocation
|
|
objectNameDotLocation; ///< Location of the "." after the object name.
|
|
ExpressionParserLocation objectFunctionOrBehaviorNameLocation; ///< Location
|
|
/// of object
|
|
/// function
|
|
/// name or
|
|
/// behavior
|
|
/// name.
|
|
ExpressionParserLocation
|
|
behaviorNameNamespaceSeparatorLocation; ///< Location of the "::"
|
|
/// separator, if any.
|
|
ExpressionParserLocation behaviorFunctionNameLocation; ///< Location of the
|
|
/// behavior function
|
|
/// name, if any.
|
|
};
|
|
|
|
/**
|
|
* \brief A function call node (either free function, object function or object
|
|
* behavior function).
|
|
* For example: "MyExtension::MyFunction(1, 2)", "MyObject.Function()" or
|
|
* "MyObject.Physics::LinearVelocity()".
|
|
*/
|
|
struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
/** \brief Construct a free function call node. */
|
|
FunctionCallNode(const gd::String &functionName_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
functionName(functionName_){};
|
|
|
|
/** \brief Construct an object function call node. */
|
|
FunctionCallNode(const gd::String &objectName_,
|
|
const gd::String &functionName_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
objectName(objectName_),
|
|
functionName(functionName_){};
|
|
|
|
/** \brief Construct a behavior function call node. */
|
|
FunctionCallNode(const gd::String &objectName_,
|
|
const gd::String &behaviorName_,
|
|
const gd::String &functionName_)
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
|
|
objectName(objectName_),
|
|
behaviorName(behaviorName_),
|
|
functionName(functionName_){};
|
|
virtual ~FunctionCallNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitFunctionCallNode(*this);
|
|
};
|
|
|
|
gd::String objectName;
|
|
gd::String behaviorName;
|
|
std::vector<std::unique_ptr<ExpressionNode>> parameters;
|
|
gd::String functionName;
|
|
|
|
ExpressionParserLocation
|
|
functionNameLocation; ///< Location of the function name.
|
|
ExpressionParserLocation
|
|
objectNameLocation; ///< Location of the object name, if any.
|
|
ExpressionParserLocation
|
|
objectNameDotLocation; ///< Location of the "." after the object name.
|
|
ExpressionParserLocation
|
|
behaviorNameLocation; ///< Location of the behavior name, if any.
|
|
ExpressionParserLocation
|
|
behaviorNameNamespaceSeparatorLocation; ///< Location of the "::"
|
|
/// separator, if any.
|
|
ExpressionParserLocation
|
|
openingParenthesisLocation; ///< Location of the "(".
|
|
ExpressionParserLocation
|
|
closingParenthesisLocation; ///< Location of the ")".
|
|
};
|
|
|
|
/**
|
|
* \brief An empty node, used when parsing failed/a syntax error was
|
|
* encountered and any other node could not make sense.
|
|
*/
|
|
struct GD_CORE_API EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
|
|
EmptyNode(const gd::String &text_ = "")
|
|
: FunctionCallOrObjectFunctionNameOrEmptyNode(), text(text_){};
|
|
virtual ~EmptyNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitEmptyNode(*this);
|
|
};
|
|
|
|
gd::String text;
|
|
};
|
|
|
|
} // namespace gd
|