mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
294 lines
8.8 KiB
C++
294 lines
8.8 KiB
C++
/*
|
|
* GDevelop Core
|
|
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
|
* reserved. This project is released under the MIT License.
|
|
*/
|
|
#ifndef GDCORE_EXPRESSIONPARSER2NODES_H
|
|
#define GDCORE_EXPRESSIONPARSER2NODES_H
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include "ExpressionParser2NodeWorker.h"
|
|
#include "GDCore/String.h"
|
|
namespace gd {
|
|
class Expression;
|
|
class ObjectsContainer;
|
|
class Platform;
|
|
class ParameterMetadata;
|
|
class ExpressionMetadata;
|
|
} // namespace gd
|
|
|
|
namespace gd {
|
|
|
|
/**
|
|
* \brief A diagnostic that can be attached to a gd::ExpressionNode.
|
|
*/
|
|
struct ExpressionParserDiagnostic {
|
|
virtual bool IsError() { return false; }
|
|
virtual const gd::String &GetMessage() { return noMessage; }
|
|
virtual size_t GetStartPosition() { return 0; }
|
|
virtual size_t GetEndPosition() { return 0; }
|
|
|
|
private:
|
|
static gd::String noMessage;
|
|
};
|
|
|
|
/**
|
|
* \brief An error that can be attached to a gd::ExpressionNode.
|
|
*/
|
|
struct ExpressionParserError : public ExpressionParserDiagnostic {
|
|
ExpressionParserError(const gd::String &type_,
|
|
const gd::String &message_,
|
|
size_t position_)
|
|
: type(type_),
|
|
message(message_),
|
|
startPosition(position_),
|
|
endPosition(position_){};
|
|
ExpressionParserError(const gd::String &type_,
|
|
const gd::String &message_,
|
|
size_t startPosition_,
|
|
size_t endPosition_)
|
|
: type(type_),
|
|
message(message_),
|
|
startPosition(startPosition_),
|
|
endPosition(endPosition_){};
|
|
virtual ~ExpressionParserError(){};
|
|
|
|
bool IsError() override { return true; }
|
|
const gd::String &GetMessage() override { return message; }
|
|
size_t GetStartPosition() override { return startPosition; }
|
|
size_t GetEndPosition() override { return endPosition; }
|
|
|
|
private:
|
|
gd::String type;
|
|
gd::String message;
|
|
size_t startPosition;
|
|
size_t endPosition;
|
|
};
|
|
|
|
/**
|
|
* \brief The base node, from which all nodes in the tree of
|
|
* an expression inherits from.
|
|
*/
|
|
struct ExpressionNode {
|
|
virtual ~ExpressionNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker){};
|
|
|
|
std::unique_ptr<ExpressionParserDiagnostic> diagnostic;
|
|
};
|
|
|
|
struct SubExpressionNode : public ExpressionNode {
|
|
SubExpressionNode(std::unique_ptr<ExpressionNode> expression_)
|
|
: 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 OperatorNode : public ExpressionNode {
|
|
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 UnaryOperatorNode : public ExpressionNode {
|
|
UnaryOperatorNode(gd::String::value_type op_) : 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".
|
|
*/
|
|
struct NumberNode : public ExpressionNode {
|
|
NumberNode(const gd::String &number_) : number(number_){};
|
|
virtual ~NumberNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitNumberNode(*this);
|
|
};
|
|
|
|
gd::String number;
|
|
};
|
|
|
|
/**
|
|
* \brief A text node. For example: "Hello World".
|
|
*/
|
|
struct TextNode : public ExpressionNode {
|
|
TextNode(const gd::String &text_) : text(text_){};
|
|
virtual ~TextNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitTextNode(*this);
|
|
};
|
|
|
|
gd::String text;
|
|
};
|
|
|
|
struct VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
|
|
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
|
|
};
|
|
|
|
/**
|
|
* \brief A variable, potentially with accessor to its children.
|
|
*
|
|
* Example: MyVariable or MyVariable.MyChildren
|
|
*
|
|
* \see gd::VariableAccessorNode
|
|
* \see gd::VariableBracketAccessorNode
|
|
*/
|
|
struct VariableNode : public ExpressionNode {
|
|
VariableNode(const gd::String &type_,
|
|
const gd::String &name_,
|
|
const gd::String &objectName_)
|
|
: type(type_), name(name_), objectName(objectName_){};
|
|
virtual ~VariableNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableNode(*this);
|
|
};
|
|
|
|
gd::String type;
|
|
gd::String name;
|
|
gd::String objectName;
|
|
|
|
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
|
|
child; // Can be nullptr if no accessor
|
|
};
|
|
|
|
/**
|
|
* \brief A bracket accessor of a variable. Example: MyChild
|
|
* in MyVariable.MyChild
|
|
*/
|
|
struct VariableAccessorNode
|
|
: public VariableAccessorOrVariableBracketAccessorNode {
|
|
VariableAccessorNode(const gd::String &name_) : name(name_){};
|
|
virtual ~VariableAccessorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableAccessorNode(*this);
|
|
};
|
|
|
|
gd::String name;
|
|
};
|
|
|
|
/**
|
|
* \brief A bracket accessor of a variable. Example: ["MyChild"]
|
|
* (in MyVariable["MyChild"]).
|
|
*/
|
|
struct VariableBracketAccessorNode
|
|
: public VariableAccessorOrVariableBracketAccessorNode {
|
|
VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_)
|
|
: expression(std::move(expression_)){};
|
|
virtual ~VariableBracketAccessorNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitVariableBracketAccessorNode(*this);
|
|
};
|
|
|
|
std::unique_ptr<ExpressionNode> expression;
|
|
};
|
|
|
|
struct IdentifierOrFunctionOrEmptyNode : public ExpressionNode {};
|
|
|
|
/**
|
|
* \brief An identifier node, usually representing an object.
|
|
*/
|
|
struct IdentifierNode : public IdentifierOrFunctionOrEmptyNode {
|
|
IdentifierNode(const gd::String &identifierName_, const gd::String &type_)
|
|
: identifierName(identifierName_), type(type_){};
|
|
virtual ~IdentifierNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitIdentifierNode(*this);
|
|
};
|
|
|
|
gd::String identifierName;
|
|
gd::String type;
|
|
};
|
|
|
|
struct FunctionOrEmptyNode : public IdentifierOrFunctionOrEmptyNode {
|
|
virtual ~FunctionOrEmptyNode(){};
|
|
void Visit(ExpressionParser2NodeWorker &worker) override{};
|
|
};
|
|
|
|
/**
|
|
* \brief A function node. For example: "MyExtension::MyFunction(1, 2)".
|
|
*/
|
|
struct FunctionNode : public FunctionOrEmptyNode {
|
|
FunctionNode(const gd::String &type_,
|
|
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
|
const ExpressionMetadata &expressionMetadata_,
|
|
const gd::String &functionName_)
|
|
: type(type_),
|
|
parameters(std::move(parameters_)),
|
|
expressionMetadata(expressionMetadata_),
|
|
functionName(functionName_){};
|
|
FunctionNode(const gd::String &type_,
|
|
const gd::String &objectName_,
|
|
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
|
const ExpressionMetadata &expressionMetadata_,
|
|
const gd::String &functionName_)
|
|
: type(type_),
|
|
objectName(objectName_),
|
|
parameters(std::move(parameters_)),
|
|
expressionMetadata(expressionMetadata_),
|
|
functionName(functionName_){};
|
|
FunctionNode(const gd::String &type_,
|
|
const gd::String &objectName_,
|
|
const gd::String &behaviorName_,
|
|
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
|
const ExpressionMetadata &expressionMetadata_,
|
|
const gd::String &functionName_)
|
|
: type(type_),
|
|
objectName(objectName_),
|
|
behaviorName(behaviorName_),
|
|
parameters(std::move(parameters_)),
|
|
expressionMetadata(expressionMetadata_),
|
|
functionName(functionName_){};
|
|
virtual ~FunctionNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitFunctionNode(*this);
|
|
};
|
|
|
|
gd::String type; // This could be removed if the type ("string" or "number")
|
|
// was stored in ExpressionMetadata.
|
|
gd::String objectName;
|
|
gd::String behaviorName;
|
|
std::vector<std::unique_ptr<ExpressionNode>> parameters;
|
|
const ExpressionMetadata &expressionMetadata;
|
|
gd::String functionName;
|
|
};
|
|
|
|
/**
|
|
* \brief An empty node, used when parsing failed/a syntax error was
|
|
* encountered and any other node could not make sense.
|
|
*/
|
|
struct EmptyNode : public FunctionOrEmptyNode {
|
|
EmptyNode(const gd::String &type_, const gd::String &text_ = "")
|
|
: type(type_), text(text_){};
|
|
virtual ~EmptyNode(){};
|
|
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
|
worker.OnVisitEmptyNode(*this);
|
|
};
|
|
|
|
gd::String type;
|
|
gd::String text;
|
|
};
|
|
|
|
} // namespace gd
|
|
|
|
#endif |