parser: add assign and label
This commit is contained in:
parent
867ee171a5
commit
cd0c9c7c8c
10
ast.cpp
10
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
2
ast.hpp
2
ast.hpp
@ -53,6 +53,8 @@ struct ast_printer_t : visitor_t<void>
|
||||
|
||||
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;
|
||||
|
@ -165,6 +165,7 @@ std::optional<token_t> 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<token_t> 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;
|
||||
|
2
main.cpp
2
main.cpp
@ -22,7 +22,7 @@ static void run(std::string source)
|
||||
lexer_t lexer(buf);
|
||||
std::vector<token_t> tokens = lexer.lex_tokens();
|
||||
parser_t parser(tokens);
|
||||
std::optional<stmt_t *> stmt_o = parser.instruction();
|
||||
std::optional<stmt_t *> stmt_o = parser.statement();
|
||||
if (stmt_o) {
|
||||
dsp::ast_printer_t p(std::cout);
|
||||
(*stmt_o)->accept(&p);
|
||||
|
37
parser.cpp
37
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<stmt_t *> parser_t::instruction()
|
||||
else return {};
|
||||
}
|
||||
|
||||
std::optional<stmt_t *> parser_t::instruction_statement()
|
||||
std::optional<stmt_t *> parser_t::statement()
|
||||
{
|
||||
// label
|
||||
// instruction
|
||||
// newline
|
||||
if (check(eol)) {
|
||||
while (!at_end_p() && check(eol)) advance();
|
||||
return statement();
|
||||
} else if (check(eof)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
stmt_t * parser_t::statement()
|
||||
{
|
||||
return nullptr;
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,8 +64,7 @@ struct parser_t
|
||||
std::optional<stmt_t *> loop();
|
||||
std::optional<stmt_t *> end();
|
||||
std::optional<stmt_t *> instruction();
|
||||
std::optional<stmt_t *> instruction_statement();
|
||||
stmt_t * statement();
|
||||
std::optional<stmt_t *> statement();
|
||||
};
|
||||
|
||||
}
|
||||
|
10
stmt.hpp
10
stmt.hpp
@ -258,7 +258,6 @@ struct nop_t : stmt_accept_t<nop_t>
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
struct assign_t : stmt_accept_t<assign_t>
|
||||
{
|
||||
assign_t(token_t name, expr_t * value)
|
||||
@ -267,6 +266,13 @@ struct assign_t : stmt_accept_t<assign_t>
|
||||
const token_t name;
|
||||
const expr_t * value;
|
||||
};
|
||||
*/
|
||||
|
||||
struct label_t : stmt_accept_t<label_t>
|
||||
{
|
||||
label_t(token_t name)
|
||||
: name(name) {}
|
||||
|
||||
const token_t name;
|
||||
};
|
||||
|
||||
} // dsp
|
||||
|
10
token.hpp
10
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,
|
||||
@ -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
|
||||
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"
|
||||
|
||||
|
@ -56,4 +56,7 @@ namespace nop {
|
||||
struct nop_t;
|
||||
}
|
||||
|
||||
struct assign_t;
|
||||
struct label_t;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user