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

View File

@ -70,6 +70,7 @@ public:
bool visit_unary_operator(unary_operator*) override; bool visit_unary_operator(unary_operator*) override;
bool visit_call_expr(call_expr*) override; bool visit_call_expr(call_expr*) override;
bool visit_call_hash(call_hash*) 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_vector(call_vector*) override;
bool visit_call_function(call_function*) override; bool visit_call_function(call_function*) override;
bool visit_slice_vector(slice_vector*) 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; return true;
} }
bool ast_visitor::visit_null_access(null_access* node) {
return true;
}
bool ast_visitor::visit_call_vector(call_vector* node) { bool ast_visitor::visit_call_vector(call_vector* node) {
for(auto i : node->get_slices()) { for(auto i : node->get_slices()) {
i->accept(this); i->accept(this);

View File

@ -26,6 +26,7 @@ public:
virtual bool visit_unary_operator(unary_operator*); virtual bool visit_unary_operator(unary_operator*);
virtual bool visit_call_expr(call_expr*); virtual bool visit_call_expr(call_expr*);
virtual bool visit_call_hash(call_hash*); 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_vector(call_vector*);
virtual bool visit_call_function(call_function*); virtual bool visit_call_function(call_function*);
virtual bool visit_slice_vector(slice_vector*); 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); visitor->visit_call_hash(this);
} }
void null_access::accept(ast_visitor* visitor) {
visitor->visit_null_access(this);
}
call_vector::~call_vector() { call_vector::~call_vector() {
for(auto i : calls) { for(auto i : calls) {
delete i; delete i;

View File

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

View File

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

View File

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