added domain model
This commit is contained in:
1 parent
18d84727ab
commit
f4450494d8
43 files changed
+1903
-234
No files matched your search
+109
-48
@@ -31,6 +31,9 @@ public:
|
||||
struct StringNode: public AstNode
|
||||
{
|
||||
std::string value;
|
||||
std::string asString() {
|
||||
return value.substr(1, value.length() - 2);
|
||||
}
|
||||
};
|
||||
|
||||
struct IdentifierNode: public AstNode
|
||||
@@ -44,6 +47,7 @@ struct NumberNode: public AstNode {
|
||||
NumberNode(): value(0) {}
|
||||
};
|
||||
|
||||
|
||||
struct CountNode: public AstNode
|
||||
{
|
||||
NumberNode first;
|
||||
@@ -54,7 +58,7 @@ struct CountNode: public AstNode
|
||||
};
|
||||
|
||||
|
||||
struct AddressSpace: public AstNode
|
||||
struct AddressSpaceNode: public AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
NumberNode start;
|
||||
@@ -62,13 +66,14 @@ struct AddressSpace: public AstNode
|
||||
};
|
||||
|
||||
|
||||
class Value: AstNode
|
||||
class ValueNode: AstNode
|
||||
{
|
||||
public:
|
||||
enum ValueType {
|
||||
INT,
|
||||
STRING,
|
||||
BOOL,
|
||||
WIRE,
|
||||
IDENTIFIER
|
||||
};
|
||||
|
||||
@@ -81,6 +86,8 @@ private:
|
||||
std::optional<std::string> identifierValue;
|
||||
|
||||
public:
|
||||
ValueNode() {};
|
||||
|
||||
ValueType getType() {
|
||||
return type;
|
||||
}
|
||||
@@ -113,43 +120,50 @@ public:
|
||||
return this->type == type;
|
||||
}
|
||||
|
||||
static Value ofBool(bool _value) {
|
||||
Value value;
|
||||
static ValueNode ofBool(bool _value) {
|
||||
ValueNode value;
|
||||
value.type = BOOL;
|
||||
value.boolValue = std::optional<bool>(_value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static Value ofInt(long long _value) {
|
||||
Value value;
|
||||
static ValueNode ofInt(long long _value) {
|
||||
ValueNode value;
|
||||
value.type = INT;
|
||||
value.intValue = std::optional<long long>(_value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static Value ofString(std::string _value) {
|
||||
Value value;
|
||||
static ValueNode ofString(std::string _value) {
|
||||
ValueNode value;
|
||||
value.type = STRING;
|
||||
value.stringValue = std::optional<std::string>(_value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static Value ofIdentifier(std::string _value) {
|
||||
Value value;
|
||||
static ValueNode ofIdentifier(std::string _value) {
|
||||
ValueNode value;
|
||||
value.type = IDENTIFIER;
|
||||
value.identifierValue = std::optional<std::string>(_value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static ValueNode ofWire(std::string _value) {
|
||||
ValueNode value;
|
||||
value.type = WIRE;
|
||||
value.identifierValue = std::optional<std::string>(_value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Condition
|
||||
struct ConditionNode
|
||||
{
|
||||
bool negated;
|
||||
IdentifierNode functionName;
|
||||
std::vector<Value> params;
|
||||
std::vector<ValueNode> params;
|
||||
};
|
||||
|
||||
class Action: AstNode {
|
||||
class ActionNode: AstNode {
|
||||
public:
|
||||
enum ActionType {
|
||||
ERROR,
|
||||
@@ -161,46 +175,47 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct IfStmt: AstNode
|
||||
struct IfStatementnode: AstNode
|
||||
{
|
||||
Condition condition;
|
||||
Action action;
|
||||
ConditionNode condition;
|
||||
ActionNode action;
|
||||
};
|
||||
|
||||
|
||||
struct Rule: AstNode
|
||||
struct RuleNode: AstNode
|
||||
{
|
||||
std::vector<IfStmt> statements;
|
||||
std::vector<IfStatementnode> statements;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct EnumerationNode: AstNode
|
||||
{
|
||||
StringNode key;
|
||||
Value value;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct Popup: AstNode
|
||||
struct PopupNode: AstNode
|
||||
{
|
||||
enum PopupType {
|
||||
AUTOMATIC,
|
||||
ON_DEMAND
|
||||
};
|
||||
|
||||
PopupType type;
|
||||
StringNode title;
|
||||
StringNode text;
|
||||
std::optional<PopupType> type;
|
||||
std::optional<StringNode> title;
|
||||
std::optional<StringNode> text;
|
||||
|
||||
bool enumerated;
|
||||
std::vector<EnumerationNode> enumeration;
|
||||
|
||||
std::vector<Rule> rules;
|
||||
std::vector<RuleNode> rules;
|
||||
};
|
||||
|
||||
struct PropertyNode: public AstNode
|
||||
{
|
||||
IdentifierNode key;
|
||||
Value value;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
|
||||
@@ -239,11 +254,9 @@ struct PinNode: AstNode
|
||||
|
||||
IdentifierNode name;
|
||||
PinType type;
|
||||
StringNode tooltip;
|
||||
|
||||
PinConnectionNode connection;
|
||||
|
||||
DisplayNode display;
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<PinConnectionNode> connection;
|
||||
std::optional<DisplayNode> display;
|
||||
};
|
||||
|
||||
|
||||
@@ -270,10 +283,10 @@ struct WireNode: public AstNode
|
||||
|
||||
struct AttributeNode: AstNode
|
||||
{
|
||||
Value::ValueType type;
|
||||
ValueNode::ValueType type;
|
||||
IdentifierNode name;
|
||||
std::optional<Value> defaultValue;
|
||||
std::optional<Popup> popup;
|
||||
std::optional<ValueNode> defaultValue;
|
||||
std::optional<PopupNode> popup;
|
||||
};
|
||||
|
||||
struct ConnectionNode: AstNode
|
||||
@@ -295,14 +308,14 @@ struct ComponentNode: AstNode
|
||||
};
|
||||
|
||||
IdentifierNode name;
|
||||
StringNode tooltip;
|
||||
StringNode source;
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<StringNode> source;
|
||||
ComponentType type;
|
||||
std::vector<Rule> rules;
|
||||
StringNode instanceName;
|
||||
CountNode count;
|
||||
DisplayNode display;
|
||||
std::vector<PinNode> pin;
|
||||
std::vector<RuleNode> rules;
|
||||
std::optional<StringNode> instanceName;
|
||||
std::optional<CountNode> count;
|
||||
std::optional<DisplayNode> display;
|
||||
std::vector<PinNode> pins;
|
||||
std::vector<AttributeNode> attributes;
|
||||
};
|
||||
|
||||
@@ -316,21 +329,21 @@ struct BusNode: AstNode
|
||||
|
||||
BusType type;
|
||||
IdentifierNode name;
|
||||
StringNode tooltip;
|
||||
CountNode count;
|
||||
DisplayNode display;
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<CountNode> count;
|
||||
std::optional<DisplayNode> display;
|
||||
|
||||
std::vector<WireNode> wires;
|
||||
};
|
||||
|
||||
struct LibraryNode: AstNode
|
||||
{
|
||||
StringNode name;
|
||||
StringNode libraryInfo;
|
||||
StringNode header;
|
||||
StringNode componentDirectory;
|
||||
std::optional<StringNode> name;
|
||||
std::optional<StringNode> libraryInfo;
|
||||
std::optional<StringNode> header;
|
||||
std::optional<StringNode> componentDirectory;
|
||||
|
||||
std::vector<AddressSpace> addressSpaces;
|
||||
std::vector<AddressSpaceNode> addressSpaces;
|
||||
|
||||
std::vector<ComponentNode> components;
|
||||
std::vector<BusNode> buses;
|
||||
@@ -339,6 +352,54 @@ struct LibraryNode: AstNode
|
||||
std::vector<PropertyNode> messages;
|
||||
};
|
||||
|
||||
// SCHEMA models
|
||||
|
||||
|
||||
struct WireInstanceNode: AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
std::optional<CountNode> position;
|
||||
std::optional<DisplayNode> display;
|
||||
};
|
||||
|
||||
struct InstanceAttributeNode: AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct InstanceNode: AstNode
|
||||
{
|
||||
IdentifierNode name;
|
||||
IdentifierNode component;
|
||||
|
||||
std::optional<CountNode> position;
|
||||
std::vector<InstanceAttributeNode> attributes;
|
||||
|
||||
std::optional<NumberNode> size;
|
||||
};
|
||||
|
||||
|
||||
struct ConnectionInstanceNode: AstNode
|
||||
{
|
||||
IdentifierNode instance;
|
||||
IdentifierNode pin;
|
||||
IdentifierNode bus;
|
||||
std::optional<IdentifierNode> wire;
|
||||
|
||||
std::vector<InstanceAttributeNode> attributes;
|
||||
};
|
||||
|
||||
|
||||
struct SchemaNode: AstNode
|
||||
{
|
||||
std::optional<StringNode> source;
|
||||
|
||||
std::vector<InstanceNode> instances;
|
||||
std::vector<WireInstanceNode> wires;
|
||||
std::vector<ConnectionInstanceNode> connections;
|
||||
|
||||
std::optional<LibraryNode> library;
|
||||
};
|
||||
|
||||
#endif // ASTNODE_H
|
||||
+224
-43
@@ -360,7 +360,7 @@ PResult<PropertyNode> ComdelParser::parseProperty(std::optional<TokenType> value
|
||||
return unexpected();
|
||||
}
|
||||
}
|
||||
Value value;
|
||||
ValueNode value;
|
||||
ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON);
|
||||
@@ -374,14 +374,14 @@ PResult<PropertyNode> ComdelParser::parseProperty(std::optional<TokenType> value
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* AddressSpace := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")"
|
||||
* AddressSpaceNode := "@address" + IDENTIFIER "(" + NUMER + "," + NUMBER + ")"
|
||||
*
|
||||
****************************************************************************/
|
||||
PResult<AddressSpace> ComdelParser::parseAddress()
|
||||
PResult<AddressSpaceNode> ComdelParser::parseAddress()
|
||||
{
|
||||
auto spanner = getSpanner();
|
||||
|
||||
AddressSpace addressSpace{};
|
||||
AddressSpaceNode addressSpace{};
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_ADDRESS);
|
||||
|
||||
@@ -439,7 +439,7 @@ PResult<ComponentNode> ComdelParser::parseComponent()
|
||||
} else if(check(TokenType::KW_DISPLAY)) {
|
||||
ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay());
|
||||
} else if(check(TokenType::KW_PIN)) {
|
||||
APPEND_OR_RETURN_IF_ERR(component.pin, parsePin());
|
||||
APPEND_OR_RETURN_IF_ERR(component.pins, parsePin());
|
||||
} else if(check(TokenType::KW_ATTRIBUTE)) {
|
||||
APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute());
|
||||
} else if(check(TokenType::KW_RULE)) {
|
||||
@@ -697,13 +697,13 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
|
||||
}
|
||||
|
||||
if(check(TokenType::INT_TYPE)) {
|
||||
attribute.type = Value::INT;
|
||||
attribute.type = ValueNode::INT;
|
||||
} else if(check(TokenType::STRING_TYPE)) {
|
||||
attribute.type = Value::STRING;
|
||||
attribute.type = ValueNode::STRING;
|
||||
} else if(check(TokenType::BOOL_TYPE)) {
|
||||
attribute.type = Value::BOOL;
|
||||
attribute.type = ValueNode::BOOL;
|
||||
} else if(check(TokenType::WIRE_TYPE)) {
|
||||
attribute.type = Value::IDENTIFIER;
|
||||
attribute.type = ValueNode::IDENTIFIER;
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
@@ -711,32 +711,32 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DEFAULT);
|
||||
|
||||
if(attribute.type == Value::BOOL) {
|
||||
if(attribute.type == ValueNode::BOOL) {
|
||||
if(check(TokenType::TRUE)) {
|
||||
attribute.defaultValue = Value::ofBool(true);
|
||||
attribute.defaultValue = ValueNode::ofBool(true);
|
||||
} else if(check(TokenType::FALSE)) {
|
||||
attribute.defaultValue = Value::ofBool(false);
|
||||
attribute.defaultValue = ValueNode::ofBool(false);
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
} else if(attribute.type == Value::INT) {
|
||||
} else if(attribute.type == ValueNode::INT) {
|
||||
if(check(TokenType::NUMBER)) {
|
||||
auto number = parseNumber();
|
||||
attribute.defaultValue = Value::ofInt(number->value);
|
||||
attribute.defaultValue = ValueNode::ofInt(number->value);
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
} else if(attribute.type == Value::STRING) {
|
||||
} else if(attribute.type == ValueNode::STRING) {
|
||||
if(check(TokenType::STRING)) {
|
||||
auto string = parseString();
|
||||
attribute.defaultValue = Value::ofString(string->value);
|
||||
attribute.defaultValue = ValueNode::ofString(string->value);
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
} else if(attribute.type == Value::IDENTIFIER) {
|
||||
} else if(attribute.type == ValueNode::IDENTIFIER) {
|
||||
if(check(TokenType::IDENTIFIER)) {
|
||||
auto identifier = parseIdentifier();
|
||||
attribute.defaultValue = Value::ofIdentifier(identifier->value);
|
||||
attribute.defaultValue = ValueNode::ofIdentifier(identifier->value);
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
@@ -744,14 +744,14 @@ PResult<AttributeNode> ComdelParser::parseAttribute() {
|
||||
|
||||
if(check(TokenType::LBRACE)) {
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
Popup popup;
|
||||
PopupNode popup;
|
||||
|
||||
if(!check(TokenType::KW_POPUP)) {
|
||||
return unexpected();
|
||||
}
|
||||
|
||||
ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup());
|
||||
attribute.popup = std::optional<Popup>(popup);
|
||||
attribute.popup = std::optional<PopupNode>(popup);
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
|
||||
}
|
||||
|
||||
@@ -770,7 +770,7 @@ PResult<EnumerationNode> ComdelParser::parseEnumeration() {
|
||||
ASSIGN_OR_RETURN_IF_ERR(key, parseString());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::EQUALS);
|
||||
|
||||
Value value;
|
||||
ValueNode value;
|
||||
ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
|
||||
|
||||
EnumerationNode node;
|
||||
@@ -782,26 +782,26 @@ PResult<EnumerationNode> ComdelParser::parseEnumeration() {
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Popup := "@popup " + ("automatic" | "on_demand") { POPUP BODY }
|
||||
* PopupNode := "@popup " + ("automatic" | "on_demand") { POPUP BODY }
|
||||
*
|
||||
****************************************************************************/
|
||||
PResult<Popup> ComdelParser::parsePopup() {
|
||||
PResult<PopupNode> ComdelParser::parsePopup() {
|
||||
auto spanner = getSpanner();
|
||||
Popup popup;
|
||||
PopupNode popup;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP);
|
||||
|
||||
if(check(TokenType::IDENTIFIER)) {
|
||||
auto type = parseIdentifier();
|
||||
if(type.value().value == "automatic") {
|
||||
popup.type = Popup::AUTOMATIC;
|
||||
popup.type = PopupNode::AUTOMATIC;
|
||||
} else if(type.value().value == "on_demand") {
|
||||
popup.type = Popup::ON_DEMAND;
|
||||
popup.type = PopupNode::ON_DEMAND;
|
||||
} else {
|
||||
return PError(SourceError{current().span, "expected type 'automatic', 'on_demand'"});
|
||||
}
|
||||
} else {
|
||||
popup.type = Popup::ON_DEMAND;
|
||||
popup.type = PopupNode::ON_DEMAND;
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
@@ -880,12 +880,12 @@ PResult<ConnectionNode> ComdelParser::parseConnection() {
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Rule := "@rule {" + if-else statements + "}"
|
||||
* RuleNode := "@rule {" + if-else statements + "}"
|
||||
*
|
||||
****************************************************************************/
|
||||
PResult<Rule> ComdelParser::parseRule() {
|
||||
PResult<RuleNode> ComdelParser::parseRule() {
|
||||
auto spanner = getSpanner();
|
||||
Rule rule;
|
||||
RuleNode rule;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_RULE);
|
||||
|
||||
@@ -910,9 +910,9 @@ PResult<Rule> ComdelParser::parseRule() {
|
||||
* IfStatement := "if(!function(params...)) { error(MESSAGE) | warning(MESSAGE) }
|
||||
*
|
||||
****************************************************************************/
|
||||
PResult<IfStmt> ComdelParser::parseIfStatement() {
|
||||
PResult<IfStatementnode> ComdelParser::parseIfStatement() {
|
||||
auto spanner = getSpanner();
|
||||
IfStmt ifStatement;
|
||||
IfStatementnode ifStatement;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::IF);
|
||||
|
||||
@@ -927,7 +927,7 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
|
||||
|
||||
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.functionName, parseIdentifier());
|
||||
|
||||
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList<Value>(std::optional<TokenType>(TokenType::LPAREN),
|
||||
ASSIGN_OR_RETURN_IF_ERR(ifStatement.condition.params, parseList<ValueNode>(std::optional<TokenType>(TokenType::LPAREN),
|
||||
TokenType::RPAREN,
|
||||
TokenType::COMMA,
|
||||
false,
|
||||
@@ -939,9 +939,9 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
||||
if(check(TokenType::ERROR)) {
|
||||
ifStatement.action.type = Action::ERROR;
|
||||
ifStatement.action.type = ActionNode::ERROR;
|
||||
} else if(check(TokenType::WARNING)) {
|
||||
ifStatement.action.type = Action::WARNING;
|
||||
ifStatement.action.type = ActionNode::WARNING;
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
@@ -957,27 +957,208 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
|
||||
return spanner(ifStatement);
|
||||
}
|
||||
|
||||
PResult<Value> ComdelParser::parseValue() {
|
||||
PResult<ValueNode> ComdelParser::parseValue() {
|
||||
auto spanner = getSpanner();
|
||||
Value value;
|
||||
ValueNode value;
|
||||
|
||||
if(check(TokenType::IDENTIFIER)) {
|
||||
value = Value::ofIdentifier(parseIdentifier()->value);
|
||||
value = ValueNode::ofIdentifier(parseIdentifier()->value);
|
||||
} else if(check(TokenType::STRING)) {
|
||||
value = Value::ofString(parseString()->value);
|
||||
value = ValueNode::ofString(parseString()->value);
|
||||
} else if(check(TokenType::NUMBER)) {
|
||||
value = Value::ofInt(parseNumber()->value);
|
||||
value = ValueNode::ofInt(parseNumber()->value);
|
||||
} else if(check(TokenType::TRUE)) {
|
||||
value = Value::ofBool(true);
|
||||
value = ValueNode::ofBool(true);
|
||||
} else if(check(TokenType::FALSE)) {
|
||||
value = Value::ofBool(false);
|
||||
value = ValueNode::ofBool(false);
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
|
||||
return spanner(value);
|
||||
//return spanner(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<SchemaNode> ComdelParser::parseSchema() {
|
||||
auto spanner = getSpanner();
|
||||
SchemaNode schema{};
|
||||
|
||||
if(check(TokenType::KW_SOURCE)) {
|
||||
bump();
|
||||
if(check(TokenType::STRING)) {
|
||||
auto source = parseString();
|
||||
schema.source = *source;
|
||||
} else {
|
||||
errors.push_back(SourceError{current().span, "expected `@source`"});
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
errors.push_back(SourceError{current().span, "expected `@source`"});
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if(!check(TokenType::KW_SCHEMA)) {
|
||||
errors.push_back(SourceError{current().span, "expected `@schema`"});
|
||||
return std::nullopt;
|
||||
}
|
||||
bump();
|
||||
if(!check(TokenType::LBRACE)) {
|
||||
errors.push_back(SourceError{current().span, "expected `{`"});
|
||||
return std::nullopt;
|
||||
}
|
||||
bump();
|
||||
|
||||
while ( ! check(TokenType::RBRACE) ) {
|
||||
PResult<poly<AstNode>> err;
|
||||
if(check(TokenType::KW_INSTANCE)){
|
||||
APPEND_OR_SET_ERR(schema.instances, parseInstance());
|
||||
} else if(check(TokenType::KW_WIRE)) {
|
||||
APPEND_OR_SET_ERR(schema.wires, parseWireInstance());
|
||||
} else if(check(TokenType::KW_CONNECTION)) {
|
||||
APPEND_OR_SET_ERR(schema.connections, parseConnectionInstance());
|
||||
} else {
|
||||
err = unexpected();
|
||||
}
|
||||
if(!err.has_value()) {
|
||||
errors.push_back(err.error());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!check(TokenType::RBRACE)) {
|
||||
errors.push_back(SourceError{current().span, "expected `}`"});
|
||||
return std::nullopt;
|
||||
} else {
|
||||
bump();
|
||||
}
|
||||
|
||||
if(!check(TokenType::END_OF_FILE)) {
|
||||
errors.push_back(SourceError{current().span, "expected `EOF`"});
|
||||
}
|
||||
|
||||
if (errors.size())
|
||||
return std::nullopt;
|
||||
|
||||
return spanner(schema);
|
||||
}
|
||||
PResult<WireInstanceNode> ComdelParser::parseWireInstance() {
|
||||
auto spanner = getSpanner();
|
||||
WireInstanceNode wireInstance;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_WIRE);
|
||||
ASSIGN_OR_RETURN_IF_ERR(wireInstance.name, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
||||
while(!check(TokenType::RBRACE)) {
|
||||
if(check(TokenType::KW_POSITION)) {
|
||||
ASSIGN_OR_RETURN_IF_ERR(wireInstance.position, parsePosition());
|
||||
} else if(check(TokenType::KW_DISPLAY)) {
|
||||
ASSIGN_OR_RETURN_IF_ERR(wireInstance.display, parseDisplay());
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
|
||||
|
||||
return spanner(wireInstance);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* CountNode := "@position (" + NumberNode + "," + NumberNode + ")"
|
||||
*
|
||||
****************************************************************************/
|
||||
PResult<CountNode> ComdelParser::parsePosition()
|
||||
{
|
||||
auto spanner = getSpanner();
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_POSITION);
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
|
||||
auto first = parseNumber();
|
||||
if(!first.has_value()) {
|
||||
return PError(first.error());
|
||||
}
|
||||
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
|
||||
auto second = parseNumber();
|
||||
if(!second.has_value()) {
|
||||
return PError(second.error());
|
||||
}
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
|
||||
|
||||
return spanner(CountNode{first.value(), second.value()});
|
||||
}
|
||||
|
||||
PResult<InstanceNode> ComdelParser::parseInstance() {
|
||||
auto spanner = getSpanner();
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_INSTANCE);
|
||||
|
||||
InstanceNode instance;
|
||||
|
||||
ASSIGN_OR_RETURN_IF_ERR(instance.name, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(instance.component, parseIdentifier());
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
||||
while(!check(TokenType::RBRACE)) {
|
||||
if(check(TokenType::KW_POSITION)) {
|
||||
ASSIGN_OR_RETURN_IF_ERR(instance.position, parsePosition());
|
||||
} else if(check(TokenType::KW_ATTRIBUTE)) {
|
||||
APPEND_OR_RETURN_IF_ERR(instance.attributes, parseInstanceAttribute());
|
||||
} else if(check(TokenType::KW_SIZE)) {
|
||||
bump();
|
||||
auto number = parseNumber();
|
||||
RETURN_IF_ERR(number);
|
||||
instance.size = *number;
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
|
||||
|
||||
return spanner(instance);
|
||||
}
|
||||
PResult<InstanceAttributeNode> ComdelParser::parseInstanceAttribute() {
|
||||
auto spanner = getSpanner();
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE);
|
||||
InstanceAttributeNode attribute;
|
||||
|
||||
ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier());
|
||||
ASSIGN_OR_RETURN_IF_ERR(attribute.value, parseValue());
|
||||
|
||||
return spanner(attribute);
|
||||
}
|
||||
PResult<ConnectionInstanceNode> ComdelParser::parseConnectionInstance() {
|
||||
auto spanner = getSpanner();
|
||||
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
|
||||
|
||||
ConnectionInstanceNode connection;
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.instance, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::DOT);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.pin, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::COMMA);
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.bus, parseIdentifier());
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RPAREN);
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
|
||||
|
||||
while(!check(TokenType::RBRACE)) {
|
||||
if(check(TokenType::KW_WIRE)) {
|
||||
bump();
|
||||
ASSIGN_OR_RETURN_IF_ERR(connection.wire, parseIdentifier());
|
||||
} else if(check(TokenType::KW_ATTRIBUTE)) {
|
||||
APPEND_OR_RETURN_IF_ERR(connection.attributes, parseInstanceAttribute());
|
||||
} else {
|
||||
return unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
|
||||
|
||||
return spanner(connection);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
|
||||
template <typename T, typename = std::enable_if<std::is_base_of<AstNode, T>::value>>
|
||||
typename std::remove_reference_t<T> operator()(T&& astNode) const {
|
||||
//astNode.span = lo.to(prevSpan);
|
||||
astNode.span = lo.to(prevSpan);
|
||||
return std::move(astNode);
|
||||
}
|
||||
};
|
||||
@@ -71,22 +71,29 @@ private:
|
||||
PResult<EnumerationNode> parseEnumeration();
|
||||
|
||||
PResult<ComponentNode> parseComponent();
|
||||
PResult<AddressSpace> parseAddress();
|
||||
PResult<AddressSpaceNode> parseAddress();
|
||||
PResult<PinNode> parsePin();
|
||||
PResult<DisplayNode> parseDisplay();
|
||||
PResult<PinConnectionNode> parsePinConnection();
|
||||
PResult<AttributeNode> parseAttribute();
|
||||
PResult<Popup> parsePopup();
|
||||
PResult<Rule> parseRule();
|
||||
PResult<PopupNode> parsePopup();
|
||||
PResult<RuleNode> parseRule();
|
||||
PResult<BusNode> parseBus();
|
||||
PResult<WireNode> parseWire();
|
||||
PResult<ConnectionNode> parseConnection();
|
||||
PResult<DisplayItemNode> parseDisplayItem();
|
||||
PResult<IfStmt> parseIfStatement();
|
||||
PResult<Value> parseValue();
|
||||
PResult<IfStatementnode> parseIfStatement();
|
||||
PResult<ValueNode> parseValue();
|
||||
|
||||
PResult<WireInstanceNode> parseWireInstance();
|
||||
PResult<CountNode> parsePosition();
|
||||
PResult<InstanceNode> parseInstance();
|
||||
PResult<InstanceAttributeNode> parseInstanceAttribute();
|
||||
PResult<ConnectionInstanceNode> parseConnectionInstance();
|
||||
|
||||
public:
|
||||
ComdelParser(std::vector<Token> tokens);
|
||||
std::optional<SchemaNode> parseSchema();
|
||||
std::optional<LibraryNode> parse();
|
||||
const std::vector<SourceError>& getErrors();
|
||||
};
|
||||
|
||||
@@ -40,3 +40,44 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
|
||||
return *unit;
|
||||
}
|
||||
|
||||
|
||||
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream)
|
||||
{
|
||||
std::ifstream in(name, std::ios::in | std::ios::binary);
|
||||
if( ! in ) {
|
||||
stream << "ERROR: cannot open file '" << name
|
||||
<< "' (file does not exist or is unreadable)" << std::endl;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string source((std::istreambuf_iterator<char>(in)),
|
||||
std::istreambuf_iterator<char>());
|
||||
ComdelLexer lexer(name, source, parseContext);
|
||||
LexerResult lexerResult = lexer.tokenize();
|
||||
|
||||
if (lexerResult.errors.size()) {
|
||||
for (auto& error : lexerResult.errors) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt; // if lexer has found errors => don't parse
|
||||
}
|
||||
|
||||
ComdelParser parser(lexerResult.tokens);
|
||||
auto unit = parser.parseSchema();
|
||||
if (!unit) {
|
||||
for (auto& error : parser.getErrors()) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if(unit->source) {
|
||||
unit->library = loadLibraryFromFile(parseContext, unit->source->asString().c_str(), stream);
|
||||
}
|
||||
|
||||
|
||||
return *unit;
|
||||
}
|
||||
@@ -8,4 +8,8 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream);
|
||||
|
||||
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream);
|
||||
|
||||
#endif // PARSERUTIL_H
|
||||
@@ -128,7 +128,7 @@ TokenTables::TokenTables() {
|
||||
add( TokenType::PIN_OUT, "out", TOKENIZABLE),
|
||||
add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE),
|
||||
|
||||
// Action types
|
||||
// ActionNode types
|
||||
add( TokenType::ERROR, "error", TOKENIZABLE),
|
||||
add( TokenType::WARNING, "warning", TOKENIZABLE),
|
||||
|
||||
|
||||
Reference in new issue
Block a user