Token refactor

This commit is contained in:
Borna Rajkovic 2022-03-29 23:08:55 +02:00
parent 48e1c48579
commit 4c921759ef
6 changed files with 338 additions and 380 deletions

View File

@ -62,6 +62,8 @@ LexerResult ComdelLexer::tokenize() {
std::string text = source.substr(tokenBegin.offset, std::string text = source.substr(tokenBegin.offset,
position.offset - tokenBegin.offset); position.offset - tokenBegin.offset);
tokenType = from_token(text, tokenType.value());
tokens.push_back(Token(*tokenType, Span(tokenBegin, position), text)); tokens.push_back(Token(*tokenType, Span(tokenBegin, position), text));
} }

View File

@ -215,45 +215,34 @@ std::optional<Library> ComdelParser::parse()
while ( ! check(TokenType::END_OF_FILE) ) { while ( ! check(TokenType::END_OF_FILE) ) {
PResult<poly<AstNode>> err; PResult<poly<AstNode>> err;
if (check(TokenType::KEYWORD)) { if(check(TokenType::KW_NAME)){
auto keyword = KeywordType::determineType(current().text);
bump(); bump();
switch (keyword) {
case KeywordType::NAME:
ASSIGN_OR_SET_ERR(library.name, parseString()); ASSIGN_OR_SET_ERR(library.name, parseString());
break; } else if(check(TokenType::KW_HEADER)) {
case KeywordType::HEADER: bump();
ASSIGN_OR_SET_ERR(library.header, parseString()); ASSIGN_OR_SET_ERR(library.header, parseString());
break; } else if(check(TokenType::KW_DIRECTORY)) {
case KeywordType::DIRECTORY: bump();
ASSIGN_OR_SET_ERR(library.componentDirectory, parseString()); ASSIGN_OR_SET_ERR(library.componentDirectory, parseString());
break; } else if(check(TokenType::KW_INFO)) {
case KeywordType::INFO: bump();
ASSIGN_OR_SET_ERR(library.libraryInfo, parseString()); ASSIGN_OR_SET_ERR(library.libraryInfo, parseString());
break; } else if(check(TokenType::KW_ADDRESS)) {
case KeywordType::ADDRESS:
APPEND_OR_SET_ERR(library.addressSpaces, parseAddress()); APPEND_OR_SET_ERR(library.addressSpaces, parseAddress());
break; } else if(check(TokenType::KW_COMPONENT)) {
case KeywordType::COMPONENT:
APPEND_OR_SET_ERR(library.components, parseComponent()); APPEND_OR_SET_ERR(library.components, parseComponent());
break; } else if(check(TokenType::KW_BUS)) {
case KeywordType::BUS:
APPEND_OR_SET_ERR(library.buses, parseBus()); APPEND_OR_SET_ERR(library.buses, parseBus());
break; } else if(check(TokenType::KW_CONNECTION)) {
case KeywordType::CONNECTION:
APPEND_OR_SET_ERR(library.connections, parseConnection()); APPEND_OR_SET_ERR(library.connections, parseConnection());
break; } else if(check(TokenType::KW_MESSAGES)) {
case KeywordType::MESSAGES: bump();
ASSIGN_OR_SET_ERR(library.messages, parseList<PropertyNode>(std::optional<TokenType>(TokenType::LBRACE), ASSIGN_OR_SET_ERR(library.messages, parseList<PropertyNode>(std::optional<TokenType>(TokenType::LBRACE),
TokenType::RBRACE, TokenType::RBRACE,
std::nullopt, std::nullopt,
false, false,
[this]{return parseProperty(std::optional<TokenType>(TokenType::STRING));} [this]{return parseProperty(std::optional<TokenType>(TokenType::STRING));}
)); ));
break;
default:
err = unexpected();
}
} else { } else {
err = unexpected(); err = unexpected();
} }
@ -324,30 +313,6 @@ PResult<NumberNode> 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 + ")" * CountNode := "@size (" + NumberNode + "," + NumberNode + ")"
@ -356,6 +321,8 @@ void ComdelParser::parseBlock()
PResult<CountNode> ComdelParser::parseCount() PResult<CountNode> ComdelParser::parseCount()
{ {
auto spanner = getSpanner(); auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_COUNT);
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
auto first = parseNumber(); auto first = parseNumber();
if(!first.has_value()) { if(!first.has_value()) {
@ -383,22 +350,18 @@ PResult<PropertyNode> ComdelParser::parseProperty(std::optional<TokenType> value
ASSIGN_OR_RETURN_IF_ERR(key, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(key, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::COLON); RETURN_IF_NOT_TOKEN(TokenType::COLON);
Value value;
if(valueType.has_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(); return unexpected();
} }
} }
if(check(TokenType::NUMBER)) { Value value;
value = Value::ofInt(parseNumber().value().value); ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
} 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();
}
RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON); RETURN_IF_NOT_TOKEN(TokenType::SEMICOLON);
@ -420,6 +383,8 @@ PResult<AddressSpace> ComdelParser::parseAddress()
AddressSpace addressSpace{}; AddressSpace addressSpace{};
RETURN_IF_NOT_TOKEN(TokenType::KW_ADDRESS);
ASSIGN_OR_RETURN_IF_ERR(addressSpace.name, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(addressSpace.name, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
ASSIGN_OR_RETURN_IF_ERR(addressSpace.start, parseNumber()); ASSIGN_OR_RETURN_IF_ERR(addressSpace.start, parseNumber());
@ -442,17 +407,16 @@ PResult<Component> ComdelParser::parseComponent()
Component component{}; Component component{};
RETURN_IF_NOT_TOKEN(TokenType::KW_COMPONENT);
ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(component.name, parseIdentifier());
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::CT_PROCESSOR)) {
auto tokenType = parseIdentifier(); bump();
if(tokenType.value().value == "processor") {
component.type = Component::PROCESSOR; component.type = Component::PROCESSOR;
} else if(tokenType.value().value == "memory") { } else if(check(TokenType::CT_MEMORY)) {
bump();
component.type = Component::MEMORY; component.type = Component::MEMORY;
} else {
return PError(SourceError{current().span, "expected 'processor' or 'memory'"});
}
} else { } else {
component.type = Component::OTHER; component.type = Component::OTHER;
} }
@ -461,37 +425,25 @@ PResult<Component> ComdelParser::parseComponent()
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
PResult<poly<AstNode>> err; PResult<poly<AstNode>> err;
if (check(TokenType::KEYWORD)) { if(check(TokenType::KW_INSTANCE_NAME)) {
auto keyword = KeywordType::determineType(current().text);
bump(); bump();
switch (keyword) {
case KeywordType::INSTANCE_NAME:
ASSIGN_OR_RETURN_IF_ERR(component.instanceName, parseString()); ASSIGN_OR_RETURN_IF_ERR(component.instanceName, parseString());
break; } else if(check(TokenType::KW_TOOLTIP)) {
case KeywordType::TOOLTIP: bump();
ASSIGN_OR_RETURN_IF_ERR(component.tooltip, parseString()); ASSIGN_OR_RETURN_IF_ERR(component.tooltip, parseString());
break; } else if(check(TokenType::KW_SOURCE)) {
case KeywordType::SOURCE: bump();
ASSIGN_OR_RETURN_IF_ERR(component.source, parseString()); ASSIGN_OR_RETURN_IF_ERR(component.source, parseString());
break; } else if(check(TokenType::KW_COUNT)) {
case KeywordType::COUNT:
ASSIGN_OR_RETURN_IF_ERR(component.count, parseCount()); ASSIGN_OR_RETURN_IF_ERR(component.count, parseCount());
break; } else if(check(TokenType::KW_DISPLAY)) {
case KeywordType::DISPLAY:
ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay()); ASSIGN_OR_RETURN_IF_ERR(component.display, parseDisplay());
break; } else if(check(TokenType::KW_PIN)) {
case KeywordType::PIN:
APPEND_OR_RETURN_IF_ERR(component.pin, parsePin()); APPEND_OR_RETURN_IF_ERR(component.pin, parsePin());
break; } else if(check(TokenType::KW_ATTRIBUTE)) {
case KeywordType::ATTRIBUTE:
APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute()); APPEND_OR_RETURN_IF_ERR(component.attributes, parseAttribute());
break; } else if(check(TokenType::KW_RULE)) {
case KeywordType::RULE:
APPEND_OR_RETURN_IF_ERR(component.rules, parseRule()); APPEND_OR_RETURN_IF_ERR(component.rules, parseRule());
break;
default:
return unexpected();
}
} else { } else {
return unexpected(); return unexpected();
} }
@ -510,6 +462,8 @@ PResult<Component> ComdelParser::parseComponent()
****************************************************************************/ ****************************************************************************/
PResult<Display> ComdelParser::parseDisplay() { PResult<Display> ComdelParser::parseDisplay() {
auto spanner = getSpanner(); auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_DISPLAY);
Display display; Display display;
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
@ -553,6 +507,8 @@ PResult<Bus> ComdelParser::parseBus() {
auto spanner = getSpanner(); auto spanner = getSpanner();
Bus bus; Bus bus;
RETURN_IF_NOT_TOKEN(TokenType::KW_BUS);
ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(bus.name, parseIdentifier());
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::IDENTIFIER)) {
@ -571,20 +527,15 @@ PResult<Bus> ComdelParser::parseBus() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
if (check(TokenType::KEYWORD)) { if(check(TokenType::KW_TOOLTIP)) {
auto keyword = KeywordType::determineType(current().text);
bump(); bump();
switch (keyword) {
case KeywordType::TOOLTIP:
ASSIGN_OR_RETURN_IF_ERR(bus.tooltip, parseString()); ASSIGN_OR_RETURN_IF_ERR(bus.tooltip, parseString());
break; } else if(check(TokenType::KW_COUNT)) {
case KeywordType::COUNT:
ASSIGN_OR_RETURN_IF_ERR(bus.count, parseCount()); ASSIGN_OR_RETURN_IF_ERR(bus.count, parseCount());
break; } else if(check(TokenType::KW_DISPLAY)) {
case KeywordType::DISPLAY:
ASSIGN_OR_RETURN_IF_ERR(bus.display, parseDisplay()); ASSIGN_OR_RETURN_IF_ERR(bus.display, parseDisplay());
break; } else if(check(TokenType::KW_WIRES)) {
case KeywordType::WIRES: bump();
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(check(TokenType::IDENTIFIER)) { while(check(TokenType::IDENTIFIER)) {
APPEND_OR_RETURN_IF_ERR(bus.wires, parseWire()); APPEND_OR_RETURN_IF_ERR(bus.wires, parseWire());
@ -594,10 +545,6 @@ PResult<Bus> ComdelParser::parseBus() {
} }
} }
RETURN_IF_NOT_TOKEN(TokenType::RBRACE); RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
break;
default:
return unexpected();
}
} else { } else {
return unexpected(); return unexpected();
} }
@ -628,24 +575,21 @@ PResult<Wire> ComdelParser::parseWire() {
wire.size.value = 1; wire.size.value = 1;
} }
if(check(TokenType::IDENTIFIER)) { // default
IdentifierNode identifier;
ASSIGN_OR_RETURN_IF_ERR(identifier, parseIdentifier());
if(identifier.value == "wire") {
wire.type = Wire::WIRE; wire.type = Wire::WIRE;
} else if(identifier.value == "wired_and") {
if(check(TokenType::WIRE_DEFAULT)) {
bump();
wire.type = Wire::WIRE;
} else if(check(TokenType::WIRE_AND)) {
bump();
wire.type = Wire::WIRED_AND; wire.type = Wire::WIRED_AND;
} else if(identifier.value == "wired_or") { } else if(check(TokenType::WIRE_OR)) {
bump();
wire.type = Wire::WIRED_OR; wire.type = Wire::WIRED_OR;
}else if(identifier.value == "r_wire") { } else if(check(TokenType::R_WIRE)) {
bump();
wire.type = Wire::R_WIRE; wire.type = Wire::R_WIRE;
} else {
return PError(SourceError{current().span, "expected 'wire', 'wired_and', 'wired_or' or 'r_wire'"});
}
} else {
wire.type = Wire::WIRE;
} }
return spanner(wire); return spanner(wire);
@ -664,43 +608,34 @@ PResult<Wire> ComdelParser::parseWire() {
PResult<Pin> ComdelParser::parsePin() { PResult<Pin> ComdelParser::parsePin() {
auto spanner = getSpanner(); auto spanner = getSpanner();
RETURN_IF_NOT_TOKEN(TokenType::KW_PIN);
Pin pin{}; Pin pin{};
ASSIGN_OR_RETURN_IF_ERR(pin.name, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(pin.name, parseIdentifier());
if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier(); if(check(TokenType::PIN_IN)) {
if(type.value().value == "InOut") { bump();
pin.type = Pin::IN_OUT;
} else if(type.value().value == "In") {
pin.type = Pin::IN; pin.type = Pin::IN;
} else if(type.value().value == "Out") { } else if(check(TokenType::PIN_OUT)) {
bump();
pin.type = Pin::OUT; pin.type = Pin::OUT;
} else { } else if(check(TokenType::PIN_IN_OUT)) {
return PError(SourceError{type.value().span, "expected 'InOut', 'In', or 'Out'"}); bump();
}
} else {
pin.type = Pin::IN_OUT; pin.type = Pin::IN_OUT;
} else {
return unexpected();
} }
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
if (check(TokenType::KEYWORD)) { if (check(TokenType::KW_TOOLTIP)) {
auto keyword = KeywordType::determineType(current().text);
bump(); bump();
switch (keyword) {
case KeywordType::TOOLTIP:
ASSIGN_OR_RETURN_IF_ERR(pin.tooltip, parseString()); ASSIGN_OR_RETURN_IF_ERR(pin.tooltip, parseString());
break; } else if (check(TokenType::KW_DISPLAY)) {
case KeywordType::DISPLAY:
ASSIGN_OR_RETURN_IF_ERR(pin.display, parseDisplay()); ASSIGN_OR_RETURN_IF_ERR(pin.display, parseDisplay());
break; } else if (check(TokenType::KW_CONNECTION)) {
case KeywordType::CONNECTION:
ASSIGN_OR_RETURN_IF_ERR(pin.connection, parsePinConnection()); ASSIGN_OR_RETURN_IF_ERR(pin.connection, parsePinConnection());
break;
default:
return unexpected();
}
} else { } else {
return unexpected(); return unexpected();
} }
@ -721,11 +656,13 @@ PResult<PinConnection> ComdelParser::parsePinConnection() {
auto spanner = getSpanner(); auto spanner = getSpanner();
PinConnection connection{}; PinConnection connection{};
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier(); auto type = parseIdentifier();
if(type.value().value == "check_only") { if(type.value().value == "check_only") {
connection.type = PinConnection::CHECK_ONLY; connection.type = PinConnection::CHECK_ONLY;
} else if(type.value().value == "In") { } else if(type.value().value == "automatically") {
connection.type = PinConnection::AUTOMATICALLY; connection.type = PinConnection::AUTOMATICALLY;
} else { } else {
return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"}); return PError(SourceError{current().span, "expected identifiers 'check_only' or 'automatically'"});
@ -751,65 +688,57 @@ PResult<Attribute> ComdelParser::parseAttribute() {
auto spanner = getSpanner(); auto spanner = getSpanner();
Attribute attribute; Attribute attribute;
RETURN_IF_NOT_TOKEN(TokenType::KW_ATTRIBUTE);
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::IDENTIFIER)) {
ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(attribute.name, parseIdentifier());
} else { } else {
return unexpected(); return unexpected();
} }
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::INT_TYPE)) {
auto type = parseIdentifier();
if(type.value().value == "int") {
attribute.type = Value::INT; attribute.type = Value::INT;
} else if(type.value().value == "string") { } else if(check(TokenType::STRING_TYPE)) {
attribute.type = Value::STRING; attribute.type = Value::STRING;
} else if(type.value().value == "bool") { } else if(check(TokenType::BOOL_TYPE)) {
attribute.type = Value::BOOL; attribute.type = Value::BOOL;
} else if(type.value().value == "wire") { } else if(check(TokenType::WIRE_TYPE)) {
attribute.type = Value::IDENTIFIER; attribute.type = Value::IDENTIFIER;
} else { } else {
return PError(SourceError{current().span, "expected type 'int', 'bool', 'string', 'wire'"}); return unexpected();
}
} 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'"});
} }
bump(); bump();
RETURN_IF_NOT_TOKEN(TokenType::DEFAULT);
if(attribute.type == Value::BOOL) { if(attribute.type == Value::BOOL) {
IdentifierNode identifier; if(check(TokenType::TRUE)) {
ASSIGN_OR_RETURN_IF_ERR(identifier, parseIdentifier());
if(identifier.value == "true") {
attribute.defaultValue = Value::ofBool(true); attribute.defaultValue = Value::ofBool(true);
} else if(identifier.value == "false") { } else if(check(TokenType::FALSE)) {
attribute.defaultValue = Value::ofBool(false); attribute.defaultValue = Value::ofBool(false);
} else { } else {
return PError(SourceError{current().span, "expected value 'true' or 'false'"}); return unexpected();
} }
} else if(attribute.type == Value::INT) { } else if(attribute.type == Value::INT) {
if(check(TokenType::NUMBER)) { if(check(TokenType::NUMBER)) {
auto number = parseNumber(); auto number = parseNumber();
attribute.defaultValue = Value::ofInt(number.value().value); attribute.defaultValue = Value::ofInt(number->value);
} else { } else {
return PError(SourceError{current().span, "expected number"}); return unexpected();
} }
} else if(attribute.type == Value::STRING) { } else if(attribute.type == Value::STRING) {
if(check(TokenType::STRING)) { if(check(TokenType::STRING)) {
auto string = parseString(); auto string = parseString();
attribute.defaultValue = Value::ofString(string.value().value); attribute.defaultValue = Value::ofString(string->value);
} else { } else {
return PError(SourceError{current().span, "expected string"}); return unexpected();
} }
} else if(attribute.type == Value::IDENTIFIER) { } else if(attribute.type == Value::IDENTIFIER) {
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::IDENTIFIER)) {
auto identifier = parseIdentifier(); auto identifier = parseIdentifier();
attribute.defaultValue = Value::ofIdentifier(identifier.value().value); attribute.defaultValue = Value::ofIdentifier(identifier->value);
} else { } else {
return PError(SourceError{current().span, "expected wire"}); return unexpected();
} }
} }
@ -817,10 +746,9 @@ PResult<Attribute> ComdelParser::parseAttribute() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
Popup popup; Popup popup;
if(!(check(TokenType::KEYWORD) && current().text == "@popup")) { if(!check(TokenType::KW_POPUP)) {
return PError(SourceError{current().span, "expected '@popup'"}); return unexpected();
} }
bump();
ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup()); ASSIGN_OR_RETURN_IF_ERR(popup, parsePopup());
attribute.popup = std::optional<Popup>(popup); attribute.popup = std::optional<Popup>(popup);
@ -838,19 +766,12 @@ PResult<Attribute> ComdelParser::parseAttribute() {
PResult<EnumerationNode> ComdelParser::parseEnumeration() { PResult<EnumerationNode> ComdelParser::parseEnumeration() {
auto spanner = getSpanner(); auto spanner = getSpanner();
StringNode key; StringNode key;
ASSIGN_OR_RETURN_IF_ERR(key, parseString()); ASSIGN_OR_RETURN_IF_ERR(key, parseString());
RETURN_IF_NOT_TOKEN(TokenType::EQUALS); RETURN_IF_NOT_TOKEN(TokenType::EQUALS);
Value value; Value value;
if(check(TokenType::NUMBER)) { ASSIGN_OR_RETURN_IF_ERR(value, parseValue());
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();
}
EnumerationNode node; EnumerationNode node;
node.key = key; node.key = key;
@ -868,6 +789,8 @@ PResult<Popup> ComdelParser::parsePopup() {
auto spanner = getSpanner(); auto spanner = getSpanner();
Popup popup; Popup popup;
RETURN_IF_NOT_TOKEN(TokenType::KW_POPUP);
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::IDENTIFIER)) {
auto type = parseIdentifier(); auto type = parseIdentifier();
if(type.value().value == "automatic") { if(type.value().value == "automatic") {
@ -884,21 +807,16 @@ PResult<Popup> ComdelParser::parsePopup() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
PResult<poly<AstNode>> err; if(check(TokenType::KW_TITLE)) {
if (check(TokenType::KEYWORD)) {
auto keyword = KeywordType::determineType(current().text);
bump(); bump();
switch (keyword) {
case KeywordType::TITLE:
ASSIGN_OR_RETURN_IF_ERR(popup.title, parseString()); ASSIGN_OR_RETURN_IF_ERR(popup.title, parseString());
break; } else if(check(TokenType::KW_TEXT)) {
case KeywordType::TEXT: bump();
ASSIGN_OR_RETURN_IF_ERR(popup.text, parseString()); ASSIGN_OR_RETURN_IF_ERR(popup.text, parseString());
break; } else if(check(TokenType::KW_RULE)) {
case KeywordType::RULE:
APPEND_OR_RETURN_IF_ERR(popup.rules, parseRule()); APPEND_OR_RETURN_IF_ERR(popup.rules, parseRule());
break; } else if(check(TokenType::KW_ENUMERATED)) {
case KeywordType::ENUMERATED: bump();
popup.enumerated = true; popup.enumerated = true;
ASSIGN_OR_RETURN_IF_ERR(popup.enumeration, ASSIGN_OR_RETURN_IF_ERR(popup.enumeration,
parseList<EnumerationNode>( parseList<EnumerationNode>(
@ -909,10 +827,6 @@ PResult<Popup> ComdelParser::parsePopup() {
[this]{ return parseEnumeration();} [this]{ return parseEnumeration();}
) )
); );
break;
default:
return unexpected();
}
} else { } else {
return unexpected(); return unexpected();
} }
@ -932,6 +846,8 @@ PResult<Connection> ComdelParser::parseConnection() {
auto spanner = getSpanner(); auto spanner = getSpanner();
Connection connection; Connection connection;
RETURN_IF_NOT_TOKEN(TokenType::KW_CONNECTION);
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
ASSIGN_OR_RETURN_IF_ERR(connection.component, parseIdentifier()); ASSIGN_OR_RETURN_IF_ERR(connection.component, parseIdentifier());
RETURN_IF_NOT_TOKEN(TokenType::DOT); RETURN_IF_NOT_TOKEN(TokenType::DOT);
@ -943,24 +859,14 @@ PResult<Connection> ComdelParser::parseConnection() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
if (check(TokenType::KEYWORD)) { if (check(TokenType::KW_ATTRIBUTE)) {
auto keyword = KeywordType::determineType(current().text);
bump();
switch (keyword) {
case KeywordType::ATTRIBUTE:
APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute()); APPEND_OR_RETURN_IF_ERR(connection.attributes, parseAttribute());
break; } else if(check(TokenType::KW_WIRES)) {
case KeywordType::WIRES: bump();
{
auto wires = parseList<IdentifierNode>(std::optional<TokenType>(TokenType::LBRACE), TokenType::RBRACE, std::optional<TokenType>(TokenType::COMMA), false, auto wires = parseList<IdentifierNode>(std::optional<TokenType>(TokenType::LBRACE), TokenType::RBRACE, std::optional<TokenType>(TokenType::COMMA), false,
[this] { return parseIdentifier(); }); [this] { return parseIdentifier(); });
RETURN_IF_ERR(wires); RETURN_IF_ERR(wires);
connection.wires = *wires; connection.wires = *wires;
}
break;
default:
return unexpected();
}
} else { } else {
return unexpected(); return unexpected();
} }
@ -981,17 +887,16 @@ PResult<Rule> ComdelParser::parseRule() {
auto spanner = getSpanner(); auto spanner = getSpanner();
Rule rule; Rule rule;
RETURN_IF_NOT_TOKEN(TokenType::KW_RULE);
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
while(!check(TokenType::RBRACE)) { while(!check(TokenType::RBRACE)) {
APPEND_OR_RETURN_IF_ERR(rule.statements, parseIfStatement()); APPEND_OR_RETURN_IF_ERR(rule.statements, parseIfStatement());
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::RBRACE)) {
IdentifierNode node; break;
ASSIGN_OR_RETURN_IF_ERR(node, parseIdentifier());
if(node.value != "else") {
return PError(SourceError{node.span, "expected 'else'"});
}
} }
RETURN_IF_NOT_TOKEN(TokenType::ELSE);
} }
RETURN_IF_NOT_TOKEN(TokenType::RBRACE); RETURN_IF_NOT_TOKEN(TokenType::RBRACE);
@ -1009,11 +914,7 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
auto spanner = getSpanner(); auto spanner = getSpanner();
IfStmt ifStatement; IfStmt ifStatement;
IdentifierNode node; RETURN_IF_NOT_TOKEN(TokenType::IF);
ASSIGN_OR_RETURN_IF_ERR(node, parseIdentifier());
if(node.value != "if") {
return unexpected();
}
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
@ -1037,17 +938,14 @@ PResult<IfStmt> ComdelParser::parseIfStatement() {
RETURN_IF_NOT_TOKEN(TokenType::LBRACE); RETURN_IF_NOT_TOKEN(TokenType::LBRACE);
if(check(TokenType::IDENTIFIER)) { if(check(TokenType::ERROR)) {
IdentifierNode action;
ASSIGN_OR_RETURN_IF_ERR(action, parseIdentifier());
if(action.value == "error") {
ifStatement.action.type = Action::ERROR; ifStatement.action.type = Action::ERROR;
} else if(action.value == "warning") { } else if(check(TokenType::WARNING)) {
ifStatement.action.type = Action::WARNING; ifStatement.action.type = Action::WARNING;
} else { } else {
return PError(SourceError{action.span, "expected 'error' of 'warning'"}); return unexpected();
}
} }
bump();
RETURN_IF_NOT_TOKEN(TokenType::LPAREN); RETURN_IF_NOT_TOKEN(TokenType::LPAREN);
ASSIGN_OR_RETURN_IF_ERR(ifStatement.action.message, parseString()); ASSIGN_OR_RETURN_IF_ERR(ifStatement.action.message, parseString());
@ -1069,6 +967,12 @@ PResult<Value> ComdelParser::parseValue() {
value = Value::ofString(parseString()->value); value = Value::ofString(parseString()->value);
} else if(check(TokenType::NUMBER)) { } else if(check(TokenType::NUMBER)) {
value = Value::ofInt(parseNumber()->value); 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); return spanner(value);

View File

@ -33,35 +33,3 @@ Token::Token(TokenType type, Span span, std::string text)
, span(std::move(span)) , span(std::move(span))
, text(std::move(text)) , text(std::move(text))
{} {}
const std::map<std::string, KeywordType::Type> 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}
};

View File

@ -56,68 +56,73 @@ enum class TokenType {
COMMENT, COMMENT,
WHITESPACE, WHITESPACE,
END_OF_FILE IF,
}; ELSE,
enum class ValueType { DEFAULT,
// TYPES
BOOL,
INT,
STRING,
COLOR,
WIRE,
ADDRESS_SPACE,
};
class KeywordType { // BOOLEAN VALUE
TRUE,
FALSE,
public:
enum Type {
// KEYWORDS // KEYWORDS
NAME, KW_NAME,
INFO, KW_INFO,
HEADER, KW_HEADER,
DIRECTORY, KW_DIRECTORY,
LIBRARY, KW_LIBRARY,
ADDRESS, KW_ADDRESS,
COMPONENT, KW_COMPONENT,
MESSAGES, KW_MESSAGES,
INSTANCE_NAME, KW_INSTANCE_NAME,
COUNT, KW_COUNT,
DISPLAY, KW_DISPLAY,
PIN, KW_PIN,
TOOLTIP, KW_TOOLTIP,
CONNECTION, KW_CONNECTION,
ATTRIBUTE, KW_ATTRIBUTE,
SOURCE, KW_SOURCE,
POPUP, KW_POPUP,
RULE, KW_RULE,
TITLE, KW_TITLE,
TEXT, KW_TEXT,
BUS, KW_BUS,
WIRES, KW_WIRES,
ENUMERATED, KW_ENUMERATED,
WIRE, KW_WIRE,
INSTANCE, KW_INSTANCE,
SCHEMA, KW_SCHEMA,
POSITION, KW_POSITION,
SIZE, KW_SIZE,
UNKNOWN KW_UNKNOWN,
};
// TYPES
INT_TYPE,
BOOL_TYPE,
STRING_TYPE,
WIRE_TYPE,
static KeywordType::Type determineType(std::string type) { // WIRE TYPES
if(keywords.count(type) == 0) { WIRE_DEFAULT,
return UNKNOWN; WIRE_AND,
} WIRE_OR,
return keywords.at(type); R_WIRE,
}
private: // PIN_TYPES
PIN_IN,
PIN_OUT,
PIN_IN_OUT,
const static std::map<std::string, KeywordType::Type> keywords; // COMPONENT TYPES
CT_MEMORY,
CT_PROCESSOR,
// ACTION TYPES
ERROR,
WARNING,
// OTHER
END_OF_FILE
}; };
struct Token { struct Token {

View File

@ -3,7 +3,8 @@
enum TokenClass { enum TokenClass {
BUILT_IN_FUNC = 1, BUILT_IN_FUNC = 1,
DATA_TYPE = 2, DATA_TYPE = 2,
KEYWORD_NAME = 4 KEYWORD_NAME = 4,
TOKENIZABLE = 8
}; };
@ -18,6 +19,8 @@ struct TokenTables {
std::unordered_map<TokenType, TokenInfo> allTokensInfo; std::unordered_map<TokenType, TokenInfo> allTokensInfo;
std::unordered_map<std::string, TokenType> keywords; std::unordered_map<std::string, TokenType> keywords;
TokenType tokenize(std::string value, TokenType initial);
void add(TokenType tokenType, const std::string& txt, void add(TokenType tokenType, const std::string& txt,
unsigned short attribs = 0); unsigned short attribs = 0);
@ -41,9 +44,9 @@ TokenTables::TokenTables() {
add( TokenType::KEYWORD, "keyword" ); add( TokenType::KEYWORD, "keyword" );
// Literals (bool is not here, it has two keywords: false and true) // Literals (bool is not here, it has two keywords: false and true)
add( TokenType::NUMBER, "number" ); add( TokenType::NUMBER, "number");
add( TokenType::STRING, "string" ); add( TokenType::STRING, "string");
add( TokenType::COLOR, "color" ); add( TokenType::COLOR, "color");
// Parentheses of all kinds // Parentheses of all kinds
add( TokenType::LPAREN, "(" ); add( TokenType::LPAREN, "(" );
@ -55,7 +58,7 @@ TokenTables::TokenTables() {
add( TokenType::LT, "<" ); add( TokenType::LT, "<" );
add( TokenType::GT, ">" ); add( TokenType::GT, ">" );
// assignments and resizes // assignments
add( TokenType::EQUALS, "=" ); add( TokenType::EQUALS, "=" );
// miscellaneous // miscellaneous
@ -66,6 +69,69 @@ TokenTables::TokenTables() {
add( TokenType::WHITESPACE, "whitespace" ); add( TokenType::WHITESPACE, "whitespace" );
add( TokenType::COMMENT, "comment" ); 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) // Built-in functions (they are also keywords)
/* /*
@ -76,11 +142,23 @@ TokenTables::TokenTables() {
} }
const std::string &tokenTypeToString(TokenType tokenType) { const std::string &tokenTypeToString(TokenType tokenType) {
return tokenTables.allTokensInfo[tokenType].text; 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) bool isBuiltInFunc(TokenType tokenType)
{ {
return tokenTables.allTokensInfo[tokenType].attributes & BUILT_IN_FUNC; return tokenTables.allTokensInfo[tokenType].attributes & BUILT_IN_FUNC;

View File

@ -11,5 +11,6 @@ const std::string& tokenTypeToString(TokenType tokenType);
bool isBuiltInFunc(TokenType tokenType); bool isBuiltInFunc(TokenType tokenType);
bool isDataType(TokenType tokenType); bool isDataType(TokenType tokenType);
TokenType from_token(std::string value, TokenType initial);
#endif // TOKENSTYPE_H #endif // TOKENSTYPE_H