schema_editor/comdel/parser/ast_nodes.h

424 lines
9.4 KiB
C++

#ifndef AST_NODE_H
#define AST_NODE_H
#include "token.h"
#include "color.h"
#include "source_error.h"
#include <optional>
#include <utility>
#include <vector>
/**
* AST base class, all AST node classes extend this class. Class contains basic
* information about nodes location in file.
*/
class AstNode {
public:
Span span;
AstNode() = default;
virtual ~AstNode();
AstNode(AstNode &&) = default;
AstNode &operator=(AstNode &&) = default;
AstNode(const AstNode &) = default;
AstNode &operator=(const AstNode &) = default;
};
template<typename T>
struct EnumNode : public AstNode {
EnumNode() = default;
explicit EnumNode(T value) : value(value) {}
T value;
};
struct StringNode : public AstNode {
std::string value;
std::string asString();
};
struct IdentifierNode : public AstNode {
std::string value;
};
struct NumberNode : public AstNode {
long long int value;
explicit NumberNode(const std::string &expression);
NumberNode() : value(0) {}
};
struct ColorNode : public AstNode {
Color color;
explicit ColorNode(const std::string &expression);
ColorNode() {}
};
struct CountNode : public AstNode {
NumberNode first;
NumberNode second;
CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {}
CountNode() = default;
};
struct AddressSpaceNode : public AstNode {
IdentifierNode name;
NumberNode start;
NumberNode end;
};
class ValueNode : public AstNode {
public:
enum ValueType {
INT,
STRING,
BOOL,
WIRE,
IDENTIFIER,
MEMORY,
NIL,
COLOR,
};
private:
EnumNode<ValueType> type;
std::optional<long long> intValue;
std::optional<std::string> stringValue;
std::optional<bool> boolValue;
std::optional<std::string> identifierValue;
std::optional<Color> colorValue;
public:
ValueNode() = default;
ValueType getType() const {
return type.value;
}
long long asInt();
std::string asString();
std::string asIdentifier();
Color asColor();
bool asBool();
bool is(ValueType valueType);
static ValueNode ofBool(bool _value);
static ValueNode ofInt(long long _value);
static ValueNode ofString(std::string _value);
static ValueNode ofIdentifier(std::string _value);
static ValueNode ofMemory(std::optional<std::string> _value);
static ValueNode ofNull();
static ValueNode ofColor(Color color);
static ValueNode ofWire(std::optional<std::string> _value);
};
struct ConditionNode {
bool negated;
IdentifierNode functionName;
std::vector<ValueNode> params;
};
class ActionNode : public AstNode {
public:
enum ActionType {
ERROR,
WARNING
};
EnumNode<ActionType> type;
StringNode message;
};
struct IfStatementNode : public AstNode {
ConditionNode condition;
ActionNode action;
};
struct RuleNode : public AstNode {
std::vector<IfStatementNode> statements;
};
struct EnumerationNode : public AstNode {
StringNode key;
ValueNode value;
};
struct PopupNode : public AstNode {
enum PopupType {
AUTOMATIC,
ON_DEMAND
};
std::optional<EnumNode<PopupType>> type;
std::optional<StringNode> title;
std::optional<StringNode> text;
bool enumerated;
std::vector<EnumerationNode> enumeration;
std::vector<RuleNode> rules;
};
struct PropertyNode : public AstNode {
IdentifierNode key;
ValueNode value;
};
struct DisplayItemNode : public AstNode {
IdentifierNode type;
std::vector<PropertyNode> values;
long long int asInt(std::vector<SourceError> *errors, const std::string &property, long long int _default = 0) {
for (auto &prop: values) {
if (prop.key.value == property) {
if (prop.value.is(ValueNode::INT)) {
return prop.value.asInt();
} else {
if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected number");
}
}
}
}
return _default;
}
Color asColor(std::vector<SourceError> *errors, const std::string &property, Color _default = Color(0, 0, 0)) {
for (auto &prop: values) {
if (prop.key.value == property) {
if (prop.value.is(ValueNode::COLOR)) {
return prop.value.asColor();
} else {
if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected number");
}
}
}
}
return _default;
}
std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
for (auto &prop: values) {
if (prop.key.value == property) {
if (prop.value.is(ValueNode::IDENTIFIER)) {
return prop.value.asIdentifier();
} else {
if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected identifier");
}
}
}
}
return _default;
}
std::string asString(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
for (auto &prop: values) {
if (prop.key.value == property) {
if (prop.value.is(ValueNode::STRING)) {
return prop.value.asString();
} else {
if (errors != nullptr) {
errors->emplace_back(prop.value.span, "expected string");
}
}
}
}
return _default;
}
};
struct DisplayNode : public AstNode {
std::vector<DisplayItemNode> items;
};
struct PinConnectionNode : public AstNode {
enum ConnectionType {
REQUIRED,
OPTIONAL
};
StringNode message;
EnumNode<ConnectionType> type;
};
struct PinNode : public AstNode {
enum PinType {
IN_OUT,
IN,
OUT
};
IdentifierNode name;
EnumNode<PinType> type;
std::optional<StringNode> tooltip;
std::optional<PinConnectionNode> connection;
std::optional<DisplayNode> display;
std::optional<std::vector<ValueNode>> wires;
};
struct WireNode : public AstNode {
enum WireType {
WIRE,
WIRED_AND,
WIRED_OR,
R_WIRE
};
EnumNode<WireType> type;
IdentifierNode name;
NumberNode size;
bool hidden = false;
bool hasTerminateWith;
ValueNode terminateWith;
};
struct AttributeNode : public AstNode {
ValueNode::ValueType type;
IdentifierNode name;
std::optional<ValueNode> defaultValue;
std::optional<PopupNode> popup;
};
struct ConnectionComponentNode : public AstNode {
IdentifierNode component;
IdentifierNode pin;
};
struct ConnectionNode : public AstNode {
ConnectionComponentNode first;
std::optional<ConnectionComponentNode> second;
IdentifierNode bus;
std::vector<AttributeNode> attributes;
std::vector<ValueNode> firstWires;
std::optional<std::vector<ValueNode>> secondWires;
};
struct ComponentNode : public AstNode {
enum ComponentType {
OTHER,
PROCESSOR,
MEMORY
};
IdentifierNode name;
std::optional<StringNode> tooltip;
std::optional<StringNode> source;
EnumNode<ComponentType> type;
std::vector<RuleNode> rules;
std::optional<IdentifierNode> instanceName;
std::optional<CountNode> count;
std::optional<DisplayNode> display;
std::vector<PinNode> pins;
std::vector<AttributeNode> attributes;
};
struct BusNode : public AstNode {
enum BusType {
AUTOMATIC,
REGULAR,
SINGLE_AUTOMATIC
};
EnumNode<BusType> type;
IdentifierNode name;
std::optional<IdentifierNode> instanceName;
std::optional<StringNode> tooltip;
std::optional<CountNode> count;
std::optional<DisplayNode> display;
std::vector<WireNode> wires;
};
struct LibraryNode : public AstNode {
std::optional<StringNode> name;
std::optional<StringNode> libraryInfo;
std::optional<StringNode> header;
std::optional<StringNode> componentDirectory;
std::optional<StringNode> componentHeader;
std::vector<AddressSpaceNode> addressSpaces;
std::vector<ComponentNode> components;
std::vector<BusNode> buses;
std::vector<ConnectionNode> connections;
std::vector<PropertyNode> messages;
};
// SCHEMA models
struct InstanceAttributeNode : public AstNode {
IdentifierNode name;
ValueNode value;
};
struct InstanceNode : public AstNode {
IdentifierNode name;
IdentifierNode component;
std::optional<CountNode> position;
std::vector<InstanceAttributeNode> attributes;
std::optional<NumberNode> size;
};
struct ConnectionComponentInstance : public AstNode {
IdentifierNode instance;
IdentifierNode pin;
};
struct ConnectionInstanceNode : public AstNode {
ConnectionComponentInstance first;
std::optional<ConnectionComponentInstance> second;
IdentifierNode bus;
std::vector<InstanceAttributeNode> attributes;
};
struct SchemaNode : public AstNode {
std::optional<StringNode> source;
std::vector<InstanceNode> instances;
std::vector<ConnectionInstanceNode> connections;
std::optional<LibraryNode> library;
};
#endif // AST_NODE_H