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");
|
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 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 s, const expr_t * a) const;
|
||||||
void parenthesize(const std::string_view s1, const std::string_view s2, 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, bar, lexeme()}};
|
||||||
case '^': return {{pos, carot, lexeme()}};
|
case '^': return {{pos, carot, lexeme()}};
|
||||||
case '=': return {{pos, equal, lexeme()}};
|
case '=': return {{pos, equal, lexeme()}};
|
||||||
|
case ':': return {{pos, colon, lexeme()}};
|
||||||
case '<':
|
case '<':
|
||||||
if (match('<')) return {{pos, left_shift, lexeme()}};
|
if (match('<')) return {{pos, left_shift, lexeme()}};
|
||||||
break;
|
break;
|
||||||
@ -206,7 +207,7 @@ std::optional<token_t> lexer_t::lex_token()
|
|||||||
} else if (alpha_p(c)) {
|
} else if (alpha_p(c)) {
|
||||||
return {_identifier()};
|
return {_identifier()};
|
||||||
} else {
|
} else {
|
||||||
error(pos.line, pos.col - 1, "Unexpected character.");
|
error(pos.line, pos.col - 1, "unexpected character");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
2
main.cpp
2
main.cpp
@ -22,7 +22,7 @@ static void run(std::string source)
|
|||||||
lexer_t lexer(buf);
|
lexer_t lexer(buf);
|
||||||
std::vector<token_t> tokens = lexer.lex_tokens();
|
std::vector<token_t> tokens = lexer.lex_tokens();
|
||||||
parser_t parser(tokens);
|
parser_t parser(tokens);
|
||||||
std::optional<stmt_t *> stmt_o = parser.instruction();
|
std::optional<stmt_t *> stmt_o = parser.statement();
|
||||||
if (stmt_o) {
|
if (stmt_o) {
|
||||||
dsp::ast_printer_t p(std::cout);
|
dsp::ast_printer_t p(std::cout);
|
||||||
(*stmt_o)->accept(&p);
|
(*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)
|
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;
|
return peek().type == token_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,17 +567,34 @@ std::optional<stmt_t *> parser_t::instruction()
|
|||||||
else return {};
|
else return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<stmt_t *> parser_t::instruction_statement()
|
std::optional<stmt_t *> parser_t::statement()
|
||||||
{
|
{
|
||||||
// label
|
if (check(eol)) {
|
||||||
// instruction
|
while (!at_end_p() && check(eol)) advance();
|
||||||
// newline
|
return statement();
|
||||||
|
} else if (check(eof)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
} else if (match(identifier)) {
|
||||||
|
token_t name = previous();
|
||||||
stmt_t * parser_t::statement()
|
if (match(colon)) {
|
||||||
{
|
return {new label_t(name)};
|
||||||
return nullptr;
|
} 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 *> loop();
|
||||||
std::optional<stmt_t *> end();
|
std::optional<stmt_t *> end();
|
||||||
std::optional<stmt_t *> instruction();
|
std::optional<stmt_t *> instruction();
|
||||||
std::optional<stmt_t *> instruction_statement();
|
std::optional<stmt_t *> statement();
|
||||||
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>
|
struct assign_t : stmt_accept_t<assign_t>
|
||||||
{
|
{
|
||||||
assign_t(token_t name, expr_t * value)
|
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 token_t name;
|
||||||
const expr_t * value;
|
const expr_t * value;
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
struct label_t : stmt_accept_t<label_t>
|
||||||
|
{
|
||||||
|
label_t(token_t name)
|
||||||
|
: name(name) {}
|
||||||
|
|
||||||
|
const token_t name;
|
||||||
|
};
|
||||||
|
|
||||||
} // dsp
|
} // dsp
|
||||||
|
10
token.hpp
10
token.hpp
@ -38,13 +38,16 @@ struct token_t {
|
|||||||
carot,
|
carot,
|
||||||
left_shift,
|
left_shift,
|
||||||
right_shift,
|
right_shift,
|
||||||
equal,
|
|
||||||
|
|
||||||
// literals
|
// literals
|
||||||
identifier,
|
identifier,
|
||||||
string,
|
string,
|
||||||
number,
|
number,
|
||||||
|
|
||||||
|
// assign and label
|
||||||
|
equal,
|
||||||
|
colon,
|
||||||
|
|
||||||
// ends
|
// ends
|
||||||
eof,
|
eof,
|
||||||
eol,
|
eol,
|
||||||
@ -91,13 +94,16 @@ struct token_t {
|
|||||||
case carot : return os << "CAROT";
|
case carot : return os << "CAROT";
|
||||||
case left_shift : return os << "LEFT_SHIFT";
|
case left_shift : return os << "LEFT_SHIFT";
|
||||||
case right_shift : return os << "RIGHT_SHIFT";
|
case right_shift : return os << "RIGHT_SHIFT";
|
||||||
case equal : return os << "EQUAL";
|
|
||||||
|
|
||||||
// literals
|
// literals
|
||||||
case identifier : return os << "IDENTIFIER";
|
case identifier : return os << "IDENTIFIER";
|
||||||
case string : return os << "STRING";
|
case string : return os << "STRING";
|
||||||
case number : return os << "NUMBER";
|
case number : return os << "NUMBER";
|
||||||
|
|
||||||
|
// assign and label
|
||||||
|
case equal : return os << "EQUAL";
|
||||||
|
case colon : return os << "COLON";
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
#include "keyword.case_inc"
|
#include "keyword.case_inc"
|
||||||
|
|
||||||
|
@ -56,4 +56,7 @@ namespace nop {
|
|||||||
struct nop_t;
|
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 end::endi_t * endi) const = 0;
|
||||||
|
|
||||||
virtual T visit(const nop::nop_t * nop) 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