From 4c921759effd4b02560392189fe9025d30d52d04 Mon Sep 17 00:00:00 2001 From: Borna Rajkovic Date: Tue, 29 Mar 2022 23:08:55 +0200 Subject: [PATCH] Token refactor --- comdel/parser/comdellexer.cpp | 2 + comdel/parser/comdelparser.cpp | 478 +++++++++++++-------------------- comdel/parser/token.cpp | 32 --- comdel/parser/token.h | 115 ++++---- comdel/parser/tokenstype.cpp | 90 ++++++- comdel/parser/tokenstype.h | 1 + 6 files changed, 338 insertions(+), 380 deletions(-) diff --git a/comdel/parser/comdellexer.cpp b/comdel/parser/comdellexer.cpp index 66b0ef8..14f41cf 100644 --- a/comdel/parser/comdellexer.cpp +++ b/comdel/parser/comdellexer.cpp @@ -62,6 +62,8 @@ LexerResult ComdelLexer::tokenize() { std::string text = source.substr(tokenBegin.offset, position.offset - tokenBegin.offset); + tokenType = from_token(text, tokenType.value()); + tokens.push_back(Token(*tokenType, Span(tokenBegin, position), text)); } diff --git a/comdel/parser/comdelparser.cpp b/comdel/parser/comdelparser.cpp index cada421..83d84f2 100644 --- a/comdel/parser/comdelparser.cpp +++ b/comdel/parser/comdelparser.cpp @@ -215,45 +215,34 @@ std::optional ComdelParser::parse() while ( ! check(TokenType::END_OF_FILE) ) { PResult> err; - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if(check(TokenType::KW_NAME)){ bump(); - switch (keyword) { - case KeywordType::NAME: - ASSIGN_OR_SET_ERR(library.name, parseString()); - break; - case KeywordType::HEADER: - ASSIGN_OR_SET_ERR(library.header, parseString()); - break; - case KeywordType::DIRECTORY: - ASSIGN_OR_SET_ERR(library.componentDirectory, parseString()); - break; - case KeywordType::INFO: - ASSIGN_OR_SET_ERR(library.libraryInfo, parseString()); - break; - case KeywordType::ADDRESS: - APPEND_OR_SET_ERR(library.addressSpaces, parseAddress()); - break; - case KeywordType::COMPONENT: - APPEND_OR_SET_ERR(library.components, parseComponent()); - break; - case KeywordType::BUS: - APPEND_OR_SET_ERR(library.buses, parseBus()); - break; - case KeywordType::CONNECTION: - APPEND_OR_SET_ERR(library.connections, parseConnection()); - break; - case KeywordType::MESSAGES: - ASSIGN_OR_SET_ERR(library.messages, parseList(std::optional(TokenType::LBRACE), - TokenType::RBRACE, - std::nullopt, - false, - [this]{return parseProperty(std::optional(TokenType::STRING));} - )); - break; - default: - err = unexpected(); - } + ASSIGN_OR_SET_ERR(library.name, parseString()); + } else if(check(TokenType::KW_HEADER)) { + bump(); + ASSIGN_OR_SET_ERR(library.header, parseString()); + } else if(check(TokenType::KW_DIRECTORY)) { + bump(); + ASSIGN_OR_SET_ERR(library.componentDirectory, parseString()); + } else if(check(TokenType::KW_INFO)) { + bump(); + ASSIGN_OR_SET_ERR(library.libraryInfo, parseString()); + } else if(check(TokenType::KW_ADDRESS)) { + APPEND_OR_SET_ERR(library.addressSpaces, parseAddress()); + } else if(check(TokenType::KW_COMPONENT)) { + APPEND_OR_SET_ERR(library.components, parseComponent()); + } else if(check(TokenType::KW_BUS)) { + APPEND_OR_SET_ERR(library.buses, parseBus()); + } else if(check(TokenType::KW_CONNECTION)) { + APPEND_OR_SET_ERR(library.connections, parseConnection()); + } else if(check(TokenType::KW_MESSAGES)) { + bump(); + ASSIGN_OR_SET_ERR(library.messages, parseList(std::optional(TokenType::LBRACE), + TokenType::RBRACE, + std::nullopt, + false, + [this]{return parseProperty(std::optional(TokenType::STRING));} + )); } else { err = unexpected(); } @@ -324,30 +313,6 @@ PResult ComdelParser::parseNumber() } - -/**************************************************************************** -* -* Used for skipping block while testing -* -****************************************************************************/ -void ComdelParser::parseBlock() -{ - int depth = 0; - if(consume(TokenType::LBRACE)) { - depth++; - } - while(depth != 0) { - if(consume(TokenType::LBRACE)) { - depth++; - } else if(consume(TokenType::RBRACE)) { - depth--; - } else { - bump(); - } - } -} - - /**************************************************************************** * * CountNode := "@size (" + NumberNode + "," + NumberNode + ")" @@ -356,6 +321,8 @@ void ComdelParser::parseBlock() PResult ComdelParser::parseCount() { auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_COUNT); + RETURN_IF_NOT_TOKEN(TokenType::LPAREN); auto first = parseNumber(); if(!first.has_value()) { @@ -383,22 +350,18 @@ PResult ComdelParser::parseProperty(std::optional value ASSIGN_OR_RETURN_IF_ERR(key, parseIdentifier()); RETURN_IF_NOT_TOKEN(TokenType::COLON); - Value value; if(valueType.has_value()) { - if(!check(*valueType)) { + if(valueType == TokenType::BOOL_TYPE) { + if(!(check(TokenType::TRUE) || check(TokenType::FALSE))) { + return unexpected(); + } + } else if(!check(*valueType)) { return unexpected(); } } - if(check(TokenType::NUMBER)) { - value = Value::ofInt(parseNumber().value().value); - } else if(check(TokenType::STRING)) { - value = Value::ofString(parseString().value().value); - } else if(check(TokenType::IDENTIFIER)) { - value = Value::ofIdentifier(parseIdentifier().value().value); - } else { - return unexpected(); - } + Value value; + ASSIGN_OR_RETURN_IF_ERR(value, parseValue()); RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON); @@ -420,6 +383,8 @@ PResult ComdelParser::parseAddress() AddressSpace addressSpace{}; + RETURN_IF_NOT_TOKEN(TokenType::KW_ADDRESS); + ASSIGN_OR_RETURN_IF_ERR(addressSpace.name, parseIdentifier()); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); ASSIGN_OR_RETURN_IF_ERR(addressSpace.start, parseNumber()); @@ -442,17 +407,16 @@ PResult ComdelParser::parseComponent() Component component{}; + RETURN_IF_NOT_TOKEN(TokenType::KW_COMPONENT); + ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier()); - if(check(TokenType::IDENTIFIER)) { - auto tokenType = parseIdentifier(); - if(tokenType.value().value == "processor") { - component.type = Component::PROCESSOR; - } else if(tokenType.value().value == "memory") { - component.type = Component::MEMORY; - } else { - return PError(SourceError{current().span, "expected 'processor' or 'memory'"}); - } + if(check(TokenType::CT_PROCESSOR)) { + bump(); + component.type = Component::PROCESSOR; + } else if(check(TokenType::CT_MEMORY)) { + bump(); + component.type = Component::MEMORY; } else { component.type = Component::OTHER; } @@ -461,37 +425,25 @@ PResult ComdelParser::parseComponent() while(!check(TokenType::RBRACE)) { PResult> err; - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if(check(TokenType::KW_INSTANCE_NAME)) { bump(); - switch (keyword) { - case KeywordType::INSTANCE_NAME: - ASSIGN_OR_RETURN_IF_ERR(component.instanceName, parseString()); - break; - case KeywordType::TOOLTIP: - ASSIGN_OR_RETURN_IF_ERR(component.tooltip, parseString()); - break; - case KeywordType::SOURCE: - ASSIGN_OR_RETURN_IF_ERR(component.source, parseString()); - break; - case KeywordType::COUNT: - ASSIGN_OR_RETURN_IF_ERR(component.count, parseCount()); - break; - case KeywordType::DISPLAY: - ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay()); - break; - case KeywordType::PIN: - APPEND_OR_RETURN_IF_ERR(component.pin, parsePin()); - break; - case KeywordType::ATTRIBUTE: - APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute()); - break; - case KeywordType::RULE: - APPEND_OR_RETURN_IF_ERR(component.rules, parseRule()); - break; - default: - return unexpected(); - } + ASSIGN_OR_RETURN_IF_ERR(component.instanceName, parseString()); + } else if(check(TokenType::KW_TOOLTIP)) { + bump(); + ASSIGN_OR_RETURN_IF_ERR(component.tooltip, parseString()); + } else if(check(TokenType::KW_SOURCE)) { + bump(); + ASSIGN_OR_RETURN_IF_ERR(component.source, parseString()); + } else if(check(TokenType::KW_COUNT)) { + ASSIGN_OR_RETURN_IF_ERR(component.count, parseCount()); + } 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()); + } else if(check(TokenType::KW_ATTRIBUTE)) { + APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute()); + } else if(check(TokenType::KW_RULE)) { + APPEND_OR_RETURN_IF_ERR(component.rules, parseRule()); } else { return unexpected(); } @@ -510,6 +462,8 @@ PResult ComdelParser::parseComponent() ****************************************************************************/ PResult ComdelParser::parseDisplay() { auto spanner = getSpanner(); + + RETURN_IF_NOT_TOKEN(TokenType::KW_DISPLAY); Display display; RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { @@ -553,6 +507,8 @@ PResult ComdelParser::parseBus() { auto spanner = getSpanner(); Bus bus; + RETURN_IF_NOT_TOKEN(TokenType::KW_BUS); + ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier()); if(check(TokenType::IDENTIFIER)) { @@ -571,33 +527,24 @@ PResult ComdelParser::parseBus() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if(check(TokenType::KW_TOOLTIP)) { bump(); - switch (keyword) { - case KeywordType::TOOLTIP: - ASSIGN_OR_RETURN_IF_ERR(bus.tooltip, parseString()); - break; - case KeywordType::COUNT: - ASSIGN_OR_RETURN_IF_ERR(bus.count, parseCount()); - break; - case KeywordType::DISPLAY: - ASSIGN_OR_RETURN_IF_ERR(bus.display, parseDisplay()); - break; - case KeywordType::WIRES: - RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - while(check(TokenType::IDENTIFIER)) { - APPEND_OR_RETURN_IF_ERR(bus.wires, parseWire()); + ASSIGN_OR_RETURN_IF_ERR(bus.tooltip, parseString()); + } else if(check(TokenType::KW_COUNT)) { + ASSIGN_OR_RETURN_IF_ERR(bus.count, parseCount()); + } else if(check(TokenType::KW_DISPLAY)) { + ASSIGN_OR_RETURN_IF_ERR(bus.display, parseDisplay()); + } else if(check(TokenType::KW_WIRES)) { + bump(); + RETURN_IF_NOT_TOKEN(TokenType::LBRACE); + while(check(TokenType::IDENTIFIER)) { + APPEND_OR_RETURN_IF_ERR(bus.wires, parseWire()); - if(check(TokenType::COMMA)) { - RETURN_IF_NOT_TOKEN(TokenType::COMMA); - } + if(check(TokenType::COMMA)) { + RETURN_IF_NOT_TOKEN(TokenType::COMMA); } - RETURN_IF_NOT_TOKEN(TokenType::RBRACE); - break; - default: - return unexpected(); } + RETURN_IF_NOT_TOKEN(TokenType::RBRACE); } else { return unexpected(); } @@ -628,24 +575,21 @@ PResult ComdelParser::parseWire() { wire.size.value = 1; } - if(check(TokenType::IDENTIFIER)) { - IdentifierNode identifier; - ASSIGN_OR_RETURN_IF_ERR(identifier, parseIdentifier()); + // default + wire.type = Wire::WIRE; - if(identifier.value == "wire") { - wire.type = Wire::WIRE; - } else if(identifier.value == "wired_and") { - wire.type = Wire::WIRED_AND; - } else if(identifier.value == "wired_or") { - wire.type = Wire::WIRED_OR; - }else if(identifier.value == "r_wire") { - wire.type = Wire::R_WIRE; - } else { - return PError(SourceError{current().span, "expected 'wire', 'wired_and', 'wired_or' or 'r_wire'"}); - } - - } else { + if(check(TokenType::WIRE_DEFAULT)) { + bump(); wire.type = Wire::WIRE; + } else if(check(TokenType::WIRE_AND)) { + bump(); + wire.type = Wire::WIRED_AND; + } else if(check(TokenType::WIRE_OR)) { + bump(); + wire.type = Wire::WIRED_OR; + } else if(check(TokenType::R_WIRE)) { + bump(); + wire.type = Wire::R_WIRE; } return spanner(wire); @@ -664,43 +608,34 @@ PResult ComdelParser::parseWire() { PResult ComdelParser::parsePin() { auto spanner = getSpanner(); + RETURN_IF_NOT_TOKEN(TokenType::KW_PIN); Pin pin{}; ASSIGN_OR_RETURN_IF_ERR(pin.name, parseIdentifier()); - if(check(TokenType::IDENTIFIER)) { - auto type = parseIdentifier(); - if(type.value().value == "InOut") { - pin.type = Pin::IN_OUT; - } else if(type.value().value == "In") { - pin.type = Pin::IN; - } else if(type.value().value == "Out") { - pin.type = Pin::OUT; - } else { - return PError(SourceError{type.value().span, "expected 'InOut', 'In', or 'Out'"}); - } - } else { + + if(check(TokenType::PIN_IN)) { + bump(); + pin.type = Pin::IN; + } else if(check(TokenType::PIN_OUT)) { + bump(); + pin.type = Pin::OUT; + } else if(check(TokenType::PIN_IN_OUT)) { + bump(); pin.type = Pin::IN_OUT; + } else { + return unexpected(); } RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if (check(TokenType::KW_TOOLTIP)) { bump(); - switch (keyword) { - case KeywordType::TOOLTIP: - ASSIGN_OR_RETURN_IF_ERR(pin.tooltip, parseString()); - break; - case KeywordType::DISPLAY: - ASSIGN_OR_RETURN_IF_ERR(pin.display, parseDisplay()); - break; - case KeywordType::CONNECTION: - ASSIGN_OR_RETURN_IF_ERR(pin.connection, parsePinConnection()); - break; - default: - return unexpected(); - } + ASSIGN_OR_RETURN_IF_ERR(pin.tooltip, parseString()); + } else if (check(TokenType::KW_DISPLAY)) { + ASSIGN_OR_RETURN_IF_ERR(pin.display, parseDisplay()); + } else if (check(TokenType::KW_CONNECTION)) { + ASSIGN_OR_RETURN_IF_ERR(pin.connection, parsePinConnection()); } else { return unexpected(); } @@ -721,11 +656,13 @@ PResult ComdelParser::parsePinConnection() { auto spanner = getSpanner(); PinConnection connection{}; + RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); + if(check(TokenType::IDENTIFIER)) { auto type = parseIdentifier(); if(type.value().value == "check_only") { connection.type = PinConnection::CHECK_ONLY; - } else if(type.value().value == "In") { + } else if(type.value().value == "automatically") { connection.type = PinConnection::AUTOMATICALLY; } else { return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); @@ -751,65 +688,57 @@ PResult ComdelParser::parseAttribute() { auto spanner = getSpanner(); Attribute attribute; + RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE); + if(check(TokenType::IDENTIFIER)) { ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier()); } else { return unexpected(); } - if(check(TokenType::IDENTIFIER)) { - auto type = parseIdentifier(); - if(type.value().value == "int") { - attribute.type = Value::INT; - } else if(type.value().value == "string") { - attribute.type = Value::STRING; - } else if(type.value().value == "bool") { - attribute.type = Value::BOOL; - } else if(type.value().value == "wire") { - attribute.type = Value::IDENTIFIER; - } else { - return PError(SourceError{current().span, "expected type 'int', 'bool', 'string', 'wire'"}); - } - + if(check(TokenType::INT_TYPE)) { + attribute.type = Value::INT; + } else if(check(TokenType::STRING_TYPE)) { + attribute.type = Value::STRING; + } else if(check(TokenType::BOOL_TYPE)) { + attribute.type = Value::BOOL; + } else if(check(TokenType::WIRE_TYPE)) { + attribute.type = Value::IDENTIFIER; } else { - return PError(SourceError{current().span, "expected type 'int', 'bool', 'string', 'wire'"}); - } - - if(!(check(TokenType::IDENTIFIER) && current().text == "default")) { - return PError(SourceError{current().span, "expected 'default'"}); + return unexpected(); } bump(); + RETURN_IF_NOT_TOKEN(TokenType::DEFAULT); + if(attribute.type == Value::BOOL) { - IdentifierNode identifier; - ASSIGN_OR_RETURN_IF_ERR(identifier, parseIdentifier()); - if(identifier.value == "true") { + if(check(TokenType::TRUE)) { attribute.defaultValue = Value::ofBool(true); - } else if(identifier.value == "false") { + } else if(check(TokenType::FALSE)) { attribute.defaultValue = Value::ofBool(false); } else { - return PError(SourceError{current().span, "expected value 'true' or 'false'"}); + return unexpected(); } } else if(attribute.type == Value::INT) { if(check(TokenType::NUMBER)) { auto number = parseNumber(); - attribute.defaultValue = Value::ofInt(number.value().value); + attribute.defaultValue = Value::ofInt(number->value); } else { - return PError(SourceError{current().span, "expected number"}); + return unexpected(); } } else if(attribute.type == Value::STRING) { if(check(TokenType::STRING)) { auto string = parseString(); - attribute.defaultValue = Value::ofString(string.value().value); + attribute.defaultValue = Value::ofString(string->value); } else { - return PError(SourceError{current().span, "expected string"}); + return unexpected(); } } else if(attribute.type == Value::IDENTIFIER) { if(check(TokenType::IDENTIFIER)) { auto identifier = parseIdentifier(); - attribute.defaultValue = Value::ofIdentifier(identifier.value().value); + attribute.defaultValue = Value::ofIdentifier(identifier->value); } else { - return PError(SourceError{current().span, "expected wire"}); + return unexpected(); } } @@ -817,10 +746,9 @@ PResult ComdelParser::parseAttribute() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); Popup popup; - if(!(check(TokenType::KEYWORD) && current().text == "@popup")) { - return PError(SourceError{current().span, "expected '@popup'"}); + if(!check(TokenType::KW_POPUP)) { + return unexpected(); } - bump(); ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup()); attribute.popup = std::optional(popup); @@ -838,19 +766,12 @@ PResult ComdelParser::parseAttribute() { PResult ComdelParser::parseEnumeration() { auto spanner = getSpanner(); StringNode key; + ASSIGN_OR_RETURN_IF_ERR(key, parseString()); RETURN_IF_NOT_TOKEN(TokenType::EQUALS); Value value; - if(check(TokenType::NUMBER)) { - value = Value::ofInt(parseNumber().value().value); - } else if(check(TokenType::STRING)) { - value = Value::ofString(parseString().value().value); - } else if(check(TokenType::IDENTIFIER)) { - value = Value::ofIdentifier(parseIdentifier().value().value); - } else { - return unexpected(); - } + ASSIGN_OR_RETURN_IF_ERR(value, parseValue()); EnumerationNode node; node.key = key; @@ -868,6 +789,8 @@ PResult ComdelParser::parsePopup() { auto spanner = getSpanner(); Popup popup; + RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP); + if(check(TokenType::IDENTIFIER)) { auto type = parseIdentifier(); if(type.value().value == "automatic") { @@ -884,35 +807,26 @@ PResult ComdelParser::parsePopup() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { - PResult> err; - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if(check(TokenType::KW_TITLE)) { bump(); - switch (keyword) { - case KeywordType::TITLE: - ASSIGN_OR_RETURN_IF_ERR(popup.title, parseString()); - break; - case KeywordType::TEXT: - ASSIGN_OR_RETURN_IF_ERR(popup.text, parseString()); - break; - case KeywordType::RULE: - APPEND_OR_RETURN_IF_ERR(popup.rules, parseRule()); - break; - case KeywordType::ENUMERATED: - popup.enumerated = true; - ASSIGN_OR_RETURN_IF_ERR(popup.enumeration, - parseList( - std::optional(TokenType::LBRACE), - TokenType::RBRACE, - std::optional(TokenType::COMMA), - true, - [this]{ return parseEnumeration();} - ) - ); - break; - default: - return unexpected(); - } + ASSIGN_OR_RETURN_IF_ERR(popup.title, parseString()); + } else if(check(TokenType::KW_TEXT)) { + bump(); + ASSIGN_OR_RETURN_IF_ERR(popup.text, parseString()); + } else if(check(TokenType::KW_RULE)) { + APPEND_OR_RETURN_IF_ERR(popup.rules, parseRule()); + } else if(check(TokenType::KW_ENUMERATED)) { + bump(); + popup.enumerated = true; + ASSIGN_OR_RETURN_IF_ERR(popup.enumeration, + parseList( + std::optional(TokenType::LBRACE), + TokenType::RBRACE, + std::optional(TokenType::COMMA), + true, + [this]{ return parseEnumeration();} + ) + ); } else { return unexpected(); } @@ -932,6 +846,8 @@ PResult ComdelParser::parseConnection() { auto spanner = getSpanner(); Connection connection; + RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION); + RETURN_IF_NOT_TOKEN(TokenType::LPAREN); ASSIGN_OR_RETURN_IF_ERR(connection.component, parseIdentifier()); RETURN_IF_NOT_TOKEN(TokenType::DOT); @@ -943,24 +859,14 @@ PResult ComdelParser::parseConnection() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { - if (check(TokenType::KEYWORD)) { - auto keyword = KeywordType::determineType(current().text); + if (check(TokenType::KW_ATTRIBUTE)) { + APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute()); + } else if(check(TokenType::KW_WIRES)) { bump(); - switch (keyword) { - case KeywordType::ATTRIBUTE: - APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute()); - break; - case KeywordType::WIRES: - { - auto wires = parseList(std::optional(TokenType::LBRACE), TokenType::RBRACE, std::optional(TokenType::COMMA), false, - [this] { return parseIdentifier(); }); - RETURN_IF_ERR(wires); - connection.wires = *wires; - } - break; - default: - return unexpected(); - } + auto wires = parseList(std::optional(TokenType::LBRACE), TokenType::RBRACE, std::optional(TokenType::COMMA), false, + [this] { return parseIdentifier(); }); + RETURN_IF_ERR(wires); + connection.wires = *wires; } else { return unexpected(); } @@ -981,17 +887,16 @@ PResult ComdelParser::parseRule() { auto spanner = getSpanner(); Rule rule; + RETURN_IF_NOT_TOKEN(TokenType::KW_RULE); + RETURN_IF_NOT_TOKEN(TokenType::LBRACE); while(!check(TokenType::RBRACE)) { APPEND_OR_RETURN_IF_ERR(rule.statements, parseIfStatement()); - if(check(TokenType::IDENTIFIER)) { - IdentifierNode node; - ASSIGN_OR_RETURN_IF_ERR(node, parseIdentifier()); - if(node.value != "else") { - return PError(SourceError{node.span, "expected 'else'"}); - } + if(check(TokenType::RBRACE)) { + break; } + RETURN_IF_NOT_TOKEN(TokenType::ELSE); } RETURN_IF_NOT_TOKEN(TokenType::RBRACE); @@ -1009,11 +914,7 @@ PResult ComdelParser::parseIfStatement() { auto spanner = getSpanner(); IfStmt ifStatement; - IdentifierNode node; - ASSIGN_OR_RETURN_IF_ERR(node, parseIdentifier()); - if(node.value != "if") { - return unexpected(); - } + RETURN_IF_NOT_TOKEN(TokenType::IF); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); @@ -1037,17 +938,14 @@ PResult ComdelParser::parseIfStatement() { RETURN_IF_NOT_TOKEN(TokenType::LBRACE); - if(check(TokenType::IDENTIFIER)) { - IdentifierNode action; - ASSIGN_OR_RETURN_IF_ERR(action, parseIdentifier()); - if(action.value == "error") { - ifStatement.action.type = Action::ERROR; - } else if(action.value == "warning") { - ifStatement.action.type = Action::WARNING; - } else { - return PError(SourceError{action.span, "expected 'error' of 'warning'"}); - } + if(check(TokenType::ERROR)) { + ifStatement.action.type = Action::ERROR; + } else if(check(TokenType::WARNING)) { + ifStatement.action.type = Action::WARNING; + } else { + return unexpected(); } + bump(); RETURN_IF_NOT_TOKEN(TokenType::LPAREN); ASSIGN_OR_RETURN_IF_ERR(ifStatement.action.message, parseString()); @@ -1069,6 +967,12 @@ PResult ComdelParser::parseValue() { value = Value::ofString(parseString()->value); } else if(check(TokenType::NUMBER)) { value = Value::ofInt(parseNumber()->value); + } else if(check(TokenType::TRUE)) { + value = Value::ofBool(true); + } else if(check(TokenType::FALSE)) { + value = Value::ofBool(false); + } else { + return unexpected(); } return spanner(value); diff --git a/comdel/parser/token.cpp b/comdel/parser/token.cpp index ba833b5..1ca7f32 100644 --- a/comdel/parser/token.cpp +++ b/comdel/parser/token.cpp @@ -33,35 +33,3 @@ Token::Token(TokenType type, Span span, std::string text) , span(std::move(span)) , text(std::move(text)) {} - - -const std::map KeywordType::keywords = { - {"@name", NAME}, - {"@info", INFO}, - {"@header", HEADER}, - {"@directory", DIRECTORY}, - {"@library", LIBRARY}, - {"@address", ADDRESS}, - {"@component", COMPONENT}, - {"@messages", MESSAGES}, - {"@instanceName", INSTANCE_NAME}, - {"@count", COUNT}, - {"@display", DISPLAY}, - {"@pin", PIN}, - {"@tooltip", TOOLTIP}, - {"@connection", CONNECTION}, - {"@attribute", ATTRIBUTE}, - {"@source", SOURCE}, - {"@popup", POPUP}, - {"@rule", RULE}, - {"@title", TITLE}, - {"@text", TEXT}, - {"@bus", BUS}, - {"@wires", WIRES}, - {"@enumerated", ENUMERATED}, - {"@wire", WIRE}, - {"@instance", INSTANCE}, - {"@schema", SCHEMA}, - {"@position", POSITION}, - {"@size", SIZE} -}; diff --git a/comdel/parser/token.h b/comdel/parser/token.h index fccb946..9b8f952 100644 --- a/comdel/parser/token.h +++ b/comdel/parser/token.h @@ -56,68 +56,73 @@ enum class TokenType { COMMENT, WHITESPACE, - END_OF_FILE -}; + IF, + ELSE, + + DEFAULT, + + // BOOLEAN VALUE + TRUE, + FALSE, + + // KEYWORDS + KW_NAME, + KW_INFO, + KW_HEADER, + KW_DIRECTORY, + KW_LIBRARY, + KW_ADDRESS, + KW_COMPONENT, + KW_MESSAGES, + KW_INSTANCE_NAME, + KW_COUNT, + KW_DISPLAY, + KW_PIN, + KW_TOOLTIP, + KW_CONNECTION, + KW_ATTRIBUTE, + KW_SOURCE, + KW_POPUP, + KW_RULE, + KW_TITLE, + KW_TEXT, + KW_BUS, + KW_WIRES, + KW_ENUMERATED, + KW_WIRE, + KW_INSTANCE, + KW_SCHEMA, + KW_POSITION, + KW_SIZE, + KW_UNKNOWN, -enum class ValueType { // TYPES - BOOL, - INT, - STRING, - COLOR, - WIRE, - ADDRESS_SPACE, -}; + INT_TYPE, + BOOL_TYPE, + STRING_TYPE, + WIRE_TYPE, -class KeywordType { + // WIRE TYPES + WIRE_DEFAULT, + WIRE_AND, + WIRE_OR, + R_WIRE, -public: + // PIN_TYPES + PIN_IN, + PIN_OUT, + PIN_IN_OUT, - enum Type { - // KEYWORDS - NAME, - INFO, - HEADER, - DIRECTORY, - LIBRARY, - ADDRESS, - COMPONENT, - MESSAGES, - INSTANCE_NAME, - COUNT, - DISPLAY, - PIN, - TOOLTIP, - CONNECTION, - ATTRIBUTE, - SOURCE, - POPUP, - RULE, - TITLE, - TEXT, - BUS, - WIRES, - ENUMERATED, - WIRE, - INSTANCE, - SCHEMA, - POSITION, - SIZE, - UNKNOWN - }; + // COMPONENT TYPES + CT_MEMORY, + CT_PROCESSOR, + // ACTION TYPES + ERROR, + WARNING, - static KeywordType::Type determineType(std::string type) { - if(keywords.count(type) == 0) { - return UNKNOWN; - } - return keywords.at(type); - } - -private: - - const static std::map keywords; - + // OTHER + END_OF_FILE }; struct Token { diff --git a/comdel/parser/tokenstype.cpp b/comdel/parser/tokenstype.cpp index 765ed19..74797a2 100644 --- a/comdel/parser/tokenstype.cpp +++ b/comdel/parser/tokenstype.cpp @@ -3,7 +3,8 @@ enum TokenClass { BUILT_IN_FUNC = 1, DATA_TYPE = 2, - KEYWORD_NAME = 4 + KEYWORD_NAME = 4, + TOKENIZABLE = 8 }; @@ -18,6 +19,8 @@ struct TokenTables { std::unordered_map allTokensInfo; std::unordered_map keywords; + TokenType tokenize(std::string value, TokenType initial); + void add(TokenType tokenType, const std::string& txt, unsigned short attribs = 0); @@ -41,9 +44,9 @@ TokenTables::TokenTables() { add( TokenType::KEYWORD, "keyword" ); // Literals (bool is not here, it has two keywords: false and true) - add( TokenType::NUMBER, "number" ); - add( TokenType::STRING, "string" ); - add( TokenType::COLOR, "color" ); + add( TokenType::NUMBER, "number"); + add( TokenType::STRING, "string"); + add( TokenType::COLOR, "color"); // Parentheses of all kinds add( TokenType::LPAREN, "(" ); @@ -55,7 +58,7 @@ TokenTables::TokenTables() { add( TokenType::LT, "<" ); add( TokenType::GT, ">" ); - // assignments and resizes + // assignments add( TokenType::EQUALS, "=" ); // miscellaneous @@ -66,6 +69,69 @@ TokenTables::TokenTables() { add( TokenType::WHITESPACE, "whitespace" ); add( TokenType::COMMENT, "comment" ); + add( TokenType::TRUE, "true", TOKENIZABLE ), + add( TokenType::FALSE, "false", TOKENIZABLE), + + add( TokenType::IF, "if", TOKENIZABLE ), + add( TokenType::ELSE, "else", TOKENIZABLE), + + add( TokenType::DEFAULT, "default", TOKENIZABLE), + + // all keywords + add( TokenType::KW_NAME, "@name", TOKENIZABLE), + add( TokenType::KW_INFO, "@info", TOKENIZABLE), + add( TokenType::KW_HEADER, "@header", TOKENIZABLE), + add( TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE), + add( TokenType::KW_LIBRARY, "@library", TOKENIZABLE), + add( TokenType::KW_ADDRESS, "@address", TOKENIZABLE), + add( TokenType::KW_COMPONENT, "@component", TOKENIZABLE), + add( TokenType::KW_MESSAGES, "@messages", TOKENIZABLE), + add( TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE), + add( TokenType::KW_COUNT, "@count", TOKENIZABLE), + add( TokenType::KW_DISPLAY, "@display", TOKENIZABLE), + add( TokenType::KW_PIN, "@pin", TOKENIZABLE), + add( TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE), + add( TokenType::KW_CONNECTION, "@connection", TOKENIZABLE), + add( TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE), + add( TokenType::KW_SOURCE, "@source", TOKENIZABLE), + add( TokenType::KW_POPUP, "@popup", TOKENIZABLE), + add( TokenType::KW_RULE, "@rule", TOKENIZABLE), + add( TokenType::KW_TITLE, "@title", TOKENIZABLE), + add( TokenType::KW_TEXT, "@text", TOKENIZABLE), + add( TokenType::KW_BUS, "@bus", TOKENIZABLE), + add( TokenType::KW_WIRES, "@wires", TOKENIZABLE), + add( TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE), + add( TokenType::KW_WIRE, "@wire", TOKENIZABLE), + add( TokenType::KW_INSTANCE, "@instance", TOKENIZABLE), + add( TokenType::KW_SCHEMA, "@schema", TOKENIZABLE), + add( TokenType::KW_POSITION, "@position", TOKENIZABLE), + add( TokenType::KW_SIZE, "@size", TOKENIZABLE), + + // All types + add( TokenType::INT_TYPE, "int", TOKENIZABLE), + add( TokenType::STRING_TYPE, "string", TOKENIZABLE), + add( TokenType::BOOL_TYPE, "bool", TOKENIZABLE), + add( TokenType::WIRE_TYPE, "wire", TOKENIZABLE), + + // Wire types + add( TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE), + add( TokenType::WIRE_AND, "wired_and", TOKENIZABLE), + add( TokenType::WIRE_OR, "wired_or", TOKENIZABLE), + add( TokenType::R_WIRE, "r_wire", TOKENIZABLE), + + // Component types + add( TokenType::CT_MEMORY, "memory", TOKENIZABLE), + add( TokenType::CT_PROCESSOR, "processor", TOKENIZABLE), + + // Pin type + add( TokenType::PIN_IN, "in", TOKENIZABLE), + add( TokenType::PIN_OUT, "out", TOKENIZABLE), + add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE), + + // Action types + add( TokenType::ERROR, "error", TOKENIZABLE), + add( TokenType::WARNING, "warning", TOKENIZABLE), + // Built-in functions (they are also keywords) /* @@ -76,11 +142,23 @@ TokenTables::TokenTables() { } - const std::string &tokenTypeToString(TokenType tokenType) { return tokenTables.allTokensInfo[tokenType].text; } +TokenType TokenTables::tokenize(std::string value, TokenType initial) { + for(auto& [key, param]: allTokensInfo) { + if(param.attributes & TOKENIZABLE && param.text == value) { + return key; + } + } + return initial; +} + +TokenType from_token(std::string value, TokenType initial) { + return tokenTables.tokenize(value, initial); +} + bool isBuiltInFunc(TokenType tokenType) { return tokenTables.allTokensInfo[tokenType].attributes & BUILT_IN_FUNC; diff --git a/comdel/parser/tokenstype.h b/comdel/parser/tokenstype.h index f250bef..b09dd07 100644 --- a/comdel/parser/tokenstype.h +++ b/comdel/parser/tokenstype.h @@ -11,5 +11,6 @@ const std::string& tokenTypeToString(TokenType tokenType); bool isBuiltInFunc(TokenType tokenType); bool isDataType(TokenType tokenType); +TokenType from_token(std::string value, TokenType initial); #endif // TOKENSTYPE_H