add parse process for `??` & `?.`

This commit is contained in:
ValKmjolnir 2024-06-04 00:49:01 +08:00
parent 32c0b93e05
commit 43c229fc72
8 changed files with 64 additions and 3 deletions

View File

@ -185,6 +185,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) {
case binary_operator::binary_type::leq: std::cout << "<="; break;
case binary_operator::binary_type::condition_and: std::cout << "and"; break;
case binary_operator::binary_type::condition_or: std::cout << "or"; break;
case binary_operator::binary_type::nullchain: std::cout << "??"; break;
}
std::cout << "\"" << format_location(node);
push_indent();
@ -241,6 +242,13 @@ bool ast_dumper::visit_call_hash(call_hash* node) {
return true;
}
bool ast_dumper::visit_null_access(null_access* node) {
dump_indent();
std::cout << "null_access " << node->get_field();
std::cout << format_location(node);
return true;
}
bool ast_dumper::visit_call_vector(call_vector* node) {
dump_indent();
std::cout << "call_vector";

View File

@ -70,6 +70,7 @@ public:
bool visit_unary_operator(unary_operator*) override;
bool visit_call_expr(call_expr*) override;
bool visit_call_hash(call_hash*) override;
bool visit_null_access(null_access*) override;
bool visit_call_vector(call_vector*) override;
bool visit_call_function(call_function*) override;
bool visit_slice_vector(slice_vector*) override;

View File

@ -116,6 +116,10 @@ bool ast_visitor::visit_call_hash(call_hash* node) {
return true;
}
bool ast_visitor::visit_null_access(null_access* node) {
return true;
}
bool ast_visitor::visit_call_vector(call_vector* node) {
for(auto i : node->get_slices()) {
i->accept(this);

View File

@ -26,6 +26,7 @@ public:
virtual bool visit_unary_operator(unary_operator*);
virtual bool visit_call_expr(call_expr*);
virtual bool visit_call_hash(call_hash*);
virtual bool visit_null_access(null_access*);
virtual bool visit_call_vector(call_vector*);
virtual bool visit_call_function(call_function*);
virtual bool visit_slice_vector(slice_vector*);

View File

@ -173,6 +173,10 @@ void call_hash::accept(ast_visitor* visitor) {
visitor->visit_call_hash(this);
}
void null_access::accept(ast_visitor* visitor) {
visitor->visit_null_access(this);
}
call_vector::~call_vector() {
for(auto i : calls) {
delete i;

View File

@ -23,6 +23,7 @@ enum class expr_type {
ast_pair, // pair of key and value in hashmap
ast_call, // mark a sub-tree of calling an identifier
ast_callh, // id.name
ast_nullaccess, // id?.name
ast_callv, // id[index]
ast_callf, // id()
ast_subvec, // id[index:index]
@ -302,7 +303,8 @@ public:
bitwise_xor,
bitwise_and,
condition_and,
condition_or
condition_or,
nullchain
};
private:
@ -389,6 +391,19 @@ public:
void accept(ast_visitor*) override;
};
class null_access: public call {
private:
std::string field;
public:
null_access(const span& location, const std::string& name):
call(location, expr_type::ast_nullaccess),
field(name) {}
~null_access() override = default;
const std::string& get_field() const {return field;}
void accept(ast_visitor*) override;
};
class call_vector: public call {
private:
std::vector<slice_vector*> calls;

View File

@ -98,7 +98,8 @@ bool parse::lookahead(tok type) {
}
bool parse::is_call(tok type) {
return type==tok::tk_lcurve || type==tok::tk_lbracket || type==tok::tk_dot;
return type==tok::tk_lcurve || type==tok::tk_lbracket ||
type==tok::tk_dot || type==tok::tk_quesdot;
}
bool parse::check_comma(const tok* panic_set) {
@ -568,7 +569,7 @@ expr* parse::and_expr() {
}
expr* parse::cmp_expr() {
auto node = additive_expr();
auto node = null_chain_expr();
while(tok::tk_cmpeq<=toks[ptr].type && toks[ptr].type<=tok::tk_geq) {
auto tmp = new binary_operator(toks[ptr].loc);
switch(toks[ptr].type) {
@ -582,6 +583,21 @@ expr* parse::cmp_expr() {
}
tmp->set_left(node);
match(toks[ptr].type);
tmp->set_right(null_chain_expr());
update_location(tmp);
node = tmp;
}
update_location(node);
return node;
}
expr* parse::null_chain_expr() {
auto node = additive_expr();
while(lookahead(tok::tk_quesques)) {
auto tmp = new binary_operator(toks[ptr].loc);
tmp->set_operator_type(binary_operator::binary_type::nullchain);
tmp->set_left(node);
match(tok::tk_quesques);
tmp->set_right(additive_expr());
update_location(tmp);
node = tmp;
@ -722,6 +738,7 @@ call* parse::call_scalar() {
case tok::tk_lcurve: return callf(); break;
case tok::tk_lbracket: return callv(); break;
case tok::tk_dot: return callh(); break;
case tok::tk_quesdot: return null_access_call(); break;
default: break;
}
// unreachable
@ -737,6 +754,15 @@ call_hash* parse::callh() {
return node;
}
null_access* parse::null_access_call() {
const auto& begin_loc = toks[ptr].loc;
match(tok::tk_quesdot);
auto node = new null_access(begin_loc, toks[ptr].str);
update_location(node);
match(tok::tk_id, "expected hashmap key"); // get key
return node;
}
call_vector* parse::callv() {
// panic set for this token is not ','
// this is the FIRST set of subvec

View File

@ -119,12 +119,14 @@ private:
expr* or_expr();
expr* and_expr();
expr* cmp_expr();
expr* null_chain_expr();
expr* additive_expr();
expr* multive_expr();
unary_operator* unary();
expr* scalar();
call* call_scalar();
call_hash* callh();
null_access* null_access_call();
call_vector* callv();
call_function* callf();
slice_vector* subvec();