diff options
author | graydon <graydon> | 2005-08-10 03:15:21 +0000 |
---|---|---|
committer | graydon <graydon> | 2005-08-10 03:15:21 +0000 |
commit | d7f3e0c5d0b0af0dcb5f8168e1184f15a0554a4e (patch) | |
tree | 905bbe1cff9ae08a6cf9f314fd4d5bc8976215fa /parse.cxx | |
parent | 0110f903329ab531bcbe9d555d5b6f6dc77d8a54 (diff) | |
download | systemtap-steved-d7f3e0c5d0b0af0dcb5f8168e1184f15a0554a4e.tar.gz systemtap-steved-d7f3e0c5d0b0af0dcb5f8168e1184f15a0554a4e.tar.xz systemtap-steved-d7f3e0c5d0b0af0dcb5f8168e1184f15a0554a4e.zip |
2005-08-09 Graydon Hoare <graydon@redhat.com>
* staptree.{cxx,h}
(target_symbol): New struct.
(*_visitor::visit_target_symbol): Support it.
(visitor::active_lvalues)
(visitor::is_active_lvalue)
(visitor::push_active_lvalue)
(visitor::pop_active_lvalue): Support lvalue-detection.
(delete_statement::visit)
(pre_crement::visit)
(post_crement::visit)
(assignment::visit): Push and pop lvalue expressions.
* elaborate.{cxx,h}
(lvalule_aware_traversing_visitor): Remove class.
(no_map_mutation_during_iteration_check)
(mutated_map_collector): Update lvalue logic.
(typeresolution_info::visit_target_symbol): Add, throw error.
* parse.{cxx,h}
(tt2str)
(tok_is)
(parser::expect_*)
(parser::peek_*): New helpers.
(parser::parse_symbol): Rewrite, support target_symbols.
* translate.cxx (c_unparser::visit_target_symbol): Implement.
* tapsets.cxx (var_expanding_copy_visitor): Update lvalue logic,
change visit_symbol to visit_target_symbol.
Diffstat (limited to 'parse.cxx')
-rw-r--r-- | parse.cxx | 189 |
1 files changed, 138 insertions, 51 deletions
@@ -55,17 +55,25 @@ parser::parse (const std::string& n, bool pr) return p.parse (); } +static string +tt2str(token_type tt) +{ + switch (tt) + { + case tok_junk: return "junk"; + case tok_identifier: return "identifier"; + case tok_operator: return "operator"; + case tok_string: return "string"; + case tok_number: return "number"; + case tok_embedded: return "embedded-code"; + } + return "unknown token"; +} ostream& operator << (ostream& o, const token& t) { - o << (t.type == tok_junk ? "junk" : - t.type == tok_identifier ? "identifier" : - t.type == tok_operator ? "operator" : - t.type == tok_string ? "string" : - t.type == tok_number ? "number" : - t.type == tok_embedded ? "embedded-code" : - "unknown token"); + o << tt2str(t.type); if (t.type != tok_embedded) // XXX: other types? { @@ -141,6 +149,70 @@ parser::peek () } +static inline bool +tok_is(token const * t, token_type tt, string const & expected) +{ + return t && t->type == tt && t->content == expected; +} + + +const token* +parser::expect_known (token_type tt, string const & expected) +{ + const token *t = next(); + if (! t && t->type == tt && t->content == expected) + throw parse_error ("expected '" + expected + "'"); + return t; +} + + +const token* +parser::expect_unknown (token_type tt, string & target) +{ + const token *t = next(); + if (!(t && t->type == tt)) + throw parse_error ("expected " + tt2str(tt)); + target = t->content; + return t; +} + + +const token* +parser::expect_op (std::string const & expected) +{ + return expect_known (tok_operator, expected); +} + + +const token* +parser::expect_kw (std::string const & expected) +{ + return expect_known (tok_identifier, expected); +} + + +const token* +parser::expect_ident (std::string & target) +{ + return expect_unknown (tok_identifier, target); +} + + +bool +parser::peek_op (std::string const & op) +{ + return tok_is (peek(), tok_operator, op); +} + + +bool +parser::peek_kw (std::string const & kw) +{ + return tok_is (peek(), tok_identifier, kw); +} + + + lexer::lexer (istream& i, const string& in): input (i), input_name (in), cursor_line (1), cursor_column (1) { } @@ -1534,41 +1606,47 @@ parser::parse_value () expression* parser::parse_symbol () { - const token* t = next (); - if (t->type != tok_identifier) - throw parse_error ("expected identifier"); + string name; + const token* t = expect_ident (name); const token* t2 = t; - string name = t->content; - t = peek (); - if (t && t->type == tok_operator && t->content == "->") + if (name.size() > 0 && name[0] == '$') { - // shorthand for process- or thread-specific array element - // map "thread->VAR" to "VAR[$tid]", - // and "process->VAR" to "VAR[$pid]" - symbol* sym = new symbol; - if (name == "thread") - sym->name = "$tid"; - else if (name == "process") - sym->name = "$pid"; - else - throw parse_error ("expected 'thread->' or 'process->'"); - struct token* t2prime = new token (*t2); - t2prime->content = sym->name; - sym->tok = t2prime; - - next (); // swallow "->" - t = next (); - if (! (t->type == tok_identifier)) - throw parse_error ("expected identifier"); - - struct arrayindex* ai = new arrayindex; - ai->tok = t; - ai->base = t->content; - ai->indexes.push_back (sym); - return ai; + // target_symbol time + target_symbol *tsym = new target_symbol; + tsym->base_name = name; + while (true) + { + string c; + if (peek_op (".")) + { + next(); + expect_ident (c); + tsym->components.push_back + (make_pair (target_symbol::comp_struct_member, c)); + } + else if (peek_op ("->")) + { + next(); + expect_ident (c); + tsym->components.push_back + (make_pair (target_symbol::comp_struct_pointer_member, c)); + } + else if (peek_op ("[")) + { + next(); + expect_unknown (tok_number, c); + expect_op ("]"); + tsym->components.push_back + (make_pair (target_symbol::comp_literal_array_index, c)); + } + else + break; + } + return tsym; } - else if (t && t->type == tok_operator && t->content == "[") // array + + if (peek_op ("[")) // array { next (); struct arrayindex* ai = new arrayindex; @@ -1577,25 +1655,29 @@ parser::parse_symbol () while (1) { ai->indexes.push_back (parse_expression ()); - t = next (); - if (t->type == tok_operator && t->content == "]") - break; - if (t->type == tok_operator && t->content == ",") - continue; + if (peek_op ("]")) + { + next(); + break; + } + else if (peek_op (",")) + { + next(); + continue; + } else throw parse_error ("expected ',' or ']'"); } return ai; } - else if (t && t->type == tok_operator && t->content == "(") // function call + else if (peek_op ("(")) // function call { next (); struct functioncall* f = new functioncall; f->tok = t2; f->function = name; // Allow empty actual parameter list - const token* t3 = peek (); - if (t3 && t3->type == tok_operator && t3->content == ")") + if (peek_op (")")) { next (); return f; @@ -1603,11 +1685,16 @@ parser::parse_symbol () while (1) { f->args.push_back (parse_expression ()); - t = next (); - if (t->type == tok_operator && t->content == ")") - break; - if (t->type == tok_operator && t->content == ",") - continue; + if (peek_op (")")) + { + next(); + break; + } + else if (peek_op (",")) + { + next(); + continue; + } else throw parse_error ("expected ',' or ')'"); } |