From cd0c9c7c8c635f2d5e1690cf297663e85c99f2cf Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 20 Aug 2023 08:45:16 +0000 Subject: [PATCH] parser: add assign and label --- ast.cpp | 10 ++++++++++ ast.hpp | 2 ++ lexer.cpp | 3 ++- main.cpp | 2 +- parser.cpp | 39 ++++++++++++++++++++++++++++----------- parser.hpp | 3 +-- stmt.hpp | 10 ++++++++-- token.hpp | 14 ++++++++++---- visitable.hpp | 3 +++ visitor.hpp | 3 +++ 10 files changed, 68 insertions(+), 21 deletions(-) diff --git a/ast.cpp b/ast.cpp index f475726..fb6a288 100644 --- a/ast.cpp +++ b/ast.cpp @@ -249,4 +249,14 @@ void ast_printer_t::visit(const nop::nop_t * nop) const parenthesize("nop"); } +void ast_printer_t::visit(const assign_t * assign) const +{ + parenthesize("assign", assign->name.lexeme, assign->value); +} + +void ast_printer_t::visit(const label_t * label) const +{ + parenthesize("label", label->name.lexeme); +} + } diff --git a/ast.hpp b/ast.hpp index 2037ec2..be783c0 100644 --- a/ast.hpp +++ b/ast.hpp @@ -53,6 +53,8 @@ struct ast_printer_t : visitor_t void visit(const nop::nop_t * nop) const; + void visit(const assign_t * assign) const; + void visit(const label_t * label) const; void parenthesize(const std::string_view s, const expr_t * a) const; void parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const; diff --git a/lexer.cpp b/lexer.cpp index 1f69039..387f85c 100644 --- a/lexer.cpp +++ b/lexer.cpp @@ -165,6 +165,7 @@ std::optional lexer_t::lex_token() case '|': return {{pos, bar, lexeme()}}; case '^': return {{pos, carot, lexeme()}}; case '=': return {{pos, equal, lexeme()}}; + case ':': return {{pos, colon, lexeme()}}; case '<': if (match('<')) return {{pos, left_shift, lexeme()}}; break; @@ -206,7 +207,7 @@ std::optional lexer_t::lex_token() } else if (alpha_p(c)) { return {_identifier()}; } else { - error(pos.line, pos.col - 1, "Unexpected character."); + error(pos.line, pos.col - 1, "unexpected character"); return {}; } break; diff --git a/main.cpp b/main.cpp index 36a9be3..00a53f8 100644 --- a/main.cpp +++ b/main.cpp @@ -22,7 +22,7 @@ static void run(std::string source) lexer_t lexer(buf); std::vector tokens = lexer.lex_tokens(); parser_t parser(tokens); - std::optional stmt_o = parser.instruction(); + std::optional stmt_o = parser.statement(); if (stmt_o) { dsp::ast_printer_t p(std::cout); (*stmt_o)->accept(&p); diff --git a/parser.cpp b/parser.cpp index e0883e6..6121e32 100644 --- a/parser.cpp +++ b/parser.cpp @@ -52,7 +52,7 @@ const token_t& parser_t::advance() bool parser_t::check(enum token_t::type_t token_type) { - if (at_end_p()) return false; + if (at_end_p() && token_type != eof) return false; return peek().type == token_type; } @@ -567,17 +567,34 @@ std::optional parser_t::instruction() else return {}; } -std::optional parser_t::instruction_statement() +std::optional parser_t::statement() { - // label - // instruction - // newline - return {}; -} - -stmt_t * parser_t::statement() -{ - return nullptr; + if (check(eol)) { + while (!at_end_p() && check(eol)) advance(); + return statement(); + } else if (check(eof)) { + return {}; + } else if (match(identifier)) { + token_t name = previous(); + if (match(colon)) { + return {new label_t(name)}; + } else if (match(equal) || match(_equ)) { + expr_t * value = expression(); + if (check(eol) || check(eof)) + return {new assign_t(name, value)}; + else + throw error(peek(), "expected eol or eof after assignment"); + } else { + throw error(peek(), "expected assignment or label"); + } + } else if (auto ins_o = instruction()) { + if (check(eol) || check(eof)) + return ins_o; + else + throw error(peek(), "expected eol or eof after instruction"); + } else { + throw error(peek(), "expected statement"); + } } } diff --git a/parser.hpp b/parser.hpp index 1fa6038..58e24ff 100644 --- a/parser.hpp +++ b/parser.hpp @@ -64,8 +64,7 @@ struct parser_t std::optional loop(); std::optional end(); std::optional instruction(); - std::optional instruction_statement(); - stmt_t * statement(); + std::optional statement(); }; } diff --git a/stmt.hpp b/stmt.hpp index 9c83246..5ce7c2c 100644 --- a/stmt.hpp +++ b/stmt.hpp @@ -258,7 +258,6 @@ struct nop_t : stmt_accept_t } -/* struct assign_t : stmt_accept_t { assign_t(token_t name, expr_t * value) @@ -267,6 +266,13 @@ struct assign_t : stmt_accept_t const token_t name; const expr_t * value; }; -*/ + +struct label_t : stmt_accept_t +{ + label_t(token_t name) + : name(name) {} + + const token_t name; +}; } // dsp diff --git a/token.hpp b/token.hpp index a36b841..636d464 100644 --- a/token.hpp +++ b/token.hpp @@ -38,13 +38,16 @@ struct token_t { carot, left_shift, right_shift, - equal, // literals identifier, string, number, + // assign and label + equal, + colon, + // ends eof, eol, @@ -79,7 +82,7 @@ struct token_t { case comma : return os << "COMMA"; case dot : return os << "DOT"; - // operators + // operators case plus : return os << "PLUS"; case minus : return os << "MINUS"; case star : return os << "STAR"; @@ -91,13 +94,16 @@ struct token_t { case carot : return os << "CAROT"; case left_shift : return os << "LEFT_SHIFT"; case right_shift : return os << "RIGHT_SHIFT"; - case equal : return os << "EQUAL"; - // literals + // literals case identifier : return os << "IDENTIFIER"; case string : return os << "STRING"; case number : return os << "NUMBER"; + // assign and label + case equal : return os << "EQUAL"; + case colon : return os << "COLON"; + // keywords #include "keyword.case_inc" diff --git a/visitable.hpp b/visitable.hpp index 0e756a4..604628d 100644 --- a/visitable.hpp +++ b/visitable.hpp @@ -56,4 +56,7 @@ namespace nop { struct nop_t; } +struct assign_t; +struct label_t; + } diff --git a/visitor.hpp b/visitor.hpp index f1ba667..ccf232c 100644 --- a/visitor.hpp +++ b/visitor.hpp @@ -43,6 +43,9 @@ struct visitor_t virtual T visit(const end::endi_t * endi) const = 0; virtual T visit(const nop::nop_t * nop) const = 0; + + virtual T visit(const assign_t * assign) const = 0; + virtual T visit(const label_t * label) const = 0; }; }