diff options
author | dsmith <dsmith> | 2006-05-16 18:51:34 +0000 |
---|---|---|
committer | dsmith <dsmith> | 2006-05-16 18:51:34 +0000 |
commit | 6e213f58c493be12eeb4f1532da3891c7baafbd5 (patch) | |
tree | 80d7812358ae6efaf71f06a2a2495f4c68439b19 /parse.cxx | |
parent | 0f8b6058e5f31c7318e5d873ad732bc9946ff1b5 (diff) | |
download | systemtap-steved-6e213f58c493be12eeb4f1532da3891c7baafbd5.tar.gz systemtap-steved-6e213f58c493be12eeb4f1532da3891c7baafbd5.tar.xz systemtap-steved-6e213f58c493be12eeb4f1532da3891c7baafbd5.zip |
2006-05-16 David Smith <dsmith@redhat.com>
* parse.cxx (parser::parser): Added initializer for 'context'
member variable.
(tt2str): Added support for new tok_keyword type.
(operator <<): Ignores keyword content when outputting error
message.
(lexer::scan): Recognizes keywords, such as 'probe', 'global',
'function', etc. and classifies them as type 'tok_keyword'. This
causes keywords to become reserved so they cannot be used for
function names, variable names, etc.
(parser::parse): Changed tok_identifier to tok_keyword when looking
for "probe", "global", or "function". Also sets context member
variable which remembers if we're in probe, global, function, or
embedded context.
(parser::parse_probe, parser::parse_statement)
(parser::parse_global, parser::parse_functiondecl)
(parser::parse_if_statement, parser::parse_delete_statement)
(parser::parse_break_statement, parser::parse_continue_statement)
(parser::parse_for_loop, parser::parse_while_loop)
(parser::parse_foreach_loop, parser::parse_array_in): Looks for
tok_keyword instead of tok_identifier.
(parser::parse_probe_point): Allows keywords as part of a probe
name, since "return" and "function" are keywords.
(parser::parse_return_statement): Looks for tok_keyword instead of
tok_identifier. Make sure we're in function context.
(parser::parse_next_statement): Looks for tok_keyword instead of
tok_identifier. Make sure we're in probe context.
* parse.h: Added parse_context enum. Added 'tok_keyword' to
token_type enum. Added parse_context 'context' member variable to
parser class.
* stap.1.in: Because the string() function has been removed,
the 'string()' function reference has been changed to a 'sprint()'
function reference.
* stapex.5.in: Ditto.
* stapfuncs.5.in: The description of the string() and hexstring()
functions has been removed.
* testsuite/buildok/context_test.stp: Calls to the string()
function were converted to sprint() function calls.
* testsuite/buildok/fifteen.stp: Ditto.
* testsuite/buildok/nineteen.stp: Ditto.
* testsuite/buildok/process_test.stp: Ditto.
* testsuite/buildok/task_test.stp: Ditto.
* testsuite/buildok/timestamp.stp: Ditto.
* testsuite/buildok/twentyone.stp: Ditto.
* testsuite/semok/args.stp: Ditto.
* testsuite/semok/seven.stp: Ditto.
* testsuite/buildok/fourteen.stp: Calls to log()/string() were
converted to a call to printf().
* testsuite/buildok/sixteen.stp: Ditto.
* testsuite/buildok/thirteen.stp: Ditto.
* testsuite/buildok/twentythree.stp: Ditto.
* testsuite/buildok/twentytwo.stp: Ditto.
* testsuite/buildok/seven.stp: Calls to the string()
function were converted to sprint() calls. Calls to the
hexstring() function were converted to sprintf() calls.
* testsuite/semok/eleven.stp: Ditto.
* testsuite/buildok/seventeen.stp: Calls to log()/hexstring() were
converted to a call to printf().
* testsuite/semko/nineteen.stp: Ditto.
* testsuite/parseok/three.stp: Because keywords are reserved, a
variable named 'string' was renamed to 'str'.
* testsuite/parseok/two.stp: Because keywords are reserved, a
variable named 'global' was renamed to 'gbl'.
* testsuite/transko/two.stp: Because the parser now checks for
'next' and 'return' statement context, a 'next' statement was
removed from a function and a 'return' statement was removed from
a probe.
Diffstat (limited to 'parse.cxx')
-rw-r--r-- | parse.cxx | 128 |
1 files changed, 86 insertions, 42 deletions
@@ -30,14 +30,14 @@ parser::parser (systemtap_session& s, istream& i, bool p): session (s), input_name ("<input>"), free_input (0), input (i, input_name, s), privileged (p), - last_t (0), next_t (0), num_errors (0) + context(con_unknown), last_t (0), next_t (0), num_errors (0) { } parser::parser (systemtap_session& s, const string& fn, bool p): session (s), input_name (fn), free_input (new ifstream (input_name.c_str(), ios::in)), input (* free_input, input_name, s), privileged (p), - last_t (0), next_t (0), num_errors (0) + context(con_unknown), last_t (0), next_t (0), num_errors (0) { } parser::~parser() @@ -72,6 +72,7 @@ tt2str(token_type tt) case tok_string: return "string"; case tok_number: return "number"; case tok_embedded: return "embedded-code"; + case tok_keyword: return "keyword"; } return "unknown token"; } @@ -91,7 +92,7 @@ operator << (ostream& o, const token& t) { o << tt2str(t.type); - if (t.type != tok_embedded) // XXX: other types? + if (t.type != tok_embedded && t.type != tok_keyword) // XXX: other types? { o << " '"; for (unsigned i=0; i<t.content.length(); i++) @@ -505,6 +506,26 @@ lexer::scan () n->content = arg; } } + else + { + if (n->content == "probe" + || n->content == "global" + || n->content == "function" + || n->content == "if" + || n->content == "else" + || n->content == "for" + || n->content == "foreach" + || n->content == "in" + || n->content == "return" + || n->content == "delete" + || n->content == "while" + || n->content == "break" + || n->content == "continue" + || n->content == "next" + || n->content == "string" + || n->content == "long") + n->type = tok_keyword; + } return n; } @@ -725,16 +746,31 @@ parser::parse () break; empty = false; - if (t->type == tok_identifier && t->content == "probe") - parse_probe (f->probes, f->aliases); - else if (t->type == tok_identifier && t->content == "global") - parse_global (f->globals); - else if (t->type == tok_identifier && t->content == "function") - parse_functiondecl (f->functions); + if (t->type == tok_keyword && t->content == "probe") + { + context = con_probe; + parse_probe (f->probes, f->aliases); + } + else if (t->type == tok_keyword && t->content == "global") + { + context = con_global; + parse_global (f->globals); + } + else if (t->type == tok_keyword && t->content == "function") + { + context = con_function; + parse_functiondecl (f->functions); + } else if (t->type == tok_embedded) - f->embeds.push_back (parse_embeddedcode ()); + { + context = con_embedded; + f->embeds.push_back (parse_embeddedcode ()); + } else - throw parse_error ("expected 'probe', 'global', 'function', or '%{'"); + { + context = con_unknown; + throw parse_error ("expected 'probe', 'global', 'function', or '%{'"); + } } catch (parse_error& pe) { @@ -782,7 +818,7 @@ parser::parse_probe (std::vector<probe *> & probe_ret, std::vector<probe_alias *> & alias_ret) { const token* t0 = next (); - if (! (t0->type == tok_identifier && t0->content == "probe")) + if (! (t0->type == tok_keyword && t0->content == "probe")) throw parse_error ("expected 'probe'"); vector<probe_point *> aliases; @@ -926,23 +962,23 @@ parser::parse_statement () } else if (t && t->type == tok_operator && t->content == "{") return parse_stmt_block (); - else if (t && t->type == tok_identifier && t->content == "if") + else if (t && t->type == tok_keyword && t->content == "if") return parse_if_statement (); - else if (t && t->type == tok_identifier && t->content == "for") + else if (t && t->type == tok_keyword && t->content == "for") return parse_for_loop (); - else if (t && t->type == tok_identifier && t->content == "foreach") + else if (t && t->type == tok_keyword && t->content == "foreach") return parse_foreach_loop (); - else if (t && t->type == tok_identifier && t->content == "return") + else if (t && t->type == tok_keyword && t->content == "return") return parse_return_statement (); - else if (t && t->type == tok_identifier && t->content == "delete") + else if (t && t->type == tok_keyword && t->content == "delete") return parse_delete_statement (); - else if (t && t->type == tok_identifier && t->content == "while") + else if (t && t->type == tok_keyword && t->content == "while") return parse_while_loop (); - else if (t && t->type == tok_identifier && t->content == "break") + else if (t && t->type == tok_keyword && t->content == "break") return parse_break_statement (); - else if (t && t->type == tok_identifier && t->content == "continue") + else if (t && t->type == tok_keyword && t->content == "continue") return parse_continue_statement (); - else if (t && t->type == tok_identifier && t->content == "next") + else if (t && t->type == tok_keyword && t->content == "next") return parse_next_statement (); // XXX: "do/while" statement? else if (t && (t->type == tok_operator || // expressions are flexible @@ -960,7 +996,7 @@ void parser::parse_global (vector <vardecl*>& globals) { const token* t0 = next (); - if (! (t0->type == tok_identifier && t0->content == "global")) + if (! (t0->type == tok_keyword && t0->content == "global")) throw parse_error ("expected 'global'"); while (1) @@ -994,12 +1030,14 @@ void parser::parse_functiondecl (std::vector<functiondecl*>& functions) { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "function")) + if (! (t->type == tok_keyword && t->content == "function")) throw parse_error ("expected 'function'"); t = next (); - if (! (t->type == tok_identifier)) + if (! (t->type == tok_identifier) + && ! (t->type == tok_keyword + && (t->content == "string" || t->content == "long"))) throw parse_error ("expected identifier"); for (unsigned i=0; i<functions.size(); i++) @@ -1014,9 +1052,9 @@ parser::parse_functiondecl (std::vector<functiondecl*>& functions) if (t->type == tok_operator && t->content == ":") { t = next (); - if (t->type == tok_identifier && t->content == "string") + if (t->type == tok_keyword && t->content == "string") fd->type = pe_string; - else if (t->type == tok_identifier && t->content == "long") + else if (t->type == tok_keyword && t->content == "long") fd->type = pe_long; else throw parse_error ("expected 'string' or 'long'"); @@ -1044,9 +1082,9 @@ parser::parse_functiondecl (std::vector<functiondecl*>& functions) if (t->type == tok_operator && t->content == ":") { t = next (); - if (t->type == tok_identifier && t->content == "string") + if (t->type == tok_keyword && t->content == "string") vd->type = pe_string; - else if (t->type == tok_identifier && t->content == "long") + else if (t->type == tok_keyword && t->content == "long") vd->type = pe_long; else throw parse_error ("expected 'string' or 'long'"); @@ -1078,8 +1116,10 @@ parser::parse_probe_point () while (1) { const token* t = next (); - if (! (t->type == tok_identifier || - (t->type == tok_operator && t->content == "*"))) + if (! (t->type == tok_identifier + // we must allow ".return" and ".function", which are keywords + || t->type == tok_keyword + || (t->type == tok_operator && t->content == "*"))) throw parse_error ("expected identifier or '*'"); if (pl->tok == 0) pl->tok = t; @@ -1160,7 +1200,7 @@ if_statement* parser::parse_if_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "if")) + if (! (t->type == tok_keyword && t->content == "if")) throw parse_error ("expected 'if'"); if_statement* s = new if_statement; s->tok = t; @@ -1178,7 +1218,7 @@ parser::parse_if_statement () s->thenblock = parse_statement (); t = peek (); - if (t && t->type == tok_identifier && t->content == "else") + if (t && t->type == tok_keyword && t->content == "else") { next (); s->elseblock = parse_statement (); @@ -1205,8 +1245,10 @@ return_statement* parser::parse_return_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "return")) + if (! (t->type == tok_keyword && t->content == "return")) throw parse_error ("expected 'return'"); + if (context != con_function) + throw parse_error ("found 'return' not in function context"); return_statement* s = new return_statement; s->tok = t; s->value = parse_expression (); @@ -1218,7 +1260,7 @@ delete_statement* parser::parse_delete_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "delete")) + if (! (t->type == tok_keyword && t->content == "delete")) throw parse_error ("expected 'delete'"); delete_statement* s = new delete_statement; s->tok = t; @@ -1231,8 +1273,10 @@ next_statement* parser::parse_next_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "next")) + if (! (t->type == tok_keyword && t->content == "next")) throw parse_error ("expected 'next'"); + if (context != con_probe) + throw parse_error ("found 'next' not in probe context"); next_statement* s = new next_statement; s->tok = t; return s; @@ -1243,7 +1287,7 @@ break_statement* parser::parse_break_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "break")) + if (! (t->type == tok_keyword && t->content == "break")) throw parse_error ("expected 'break'"); break_statement* s = new break_statement; s->tok = t; @@ -1255,7 +1299,7 @@ continue_statement* parser::parse_continue_statement () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "continue")) + if (! (t->type == tok_keyword && t->content == "continue")) throw parse_error ("expected 'continue'"); continue_statement* s = new continue_statement; s->tok = t; @@ -1267,7 +1311,7 @@ for_loop* parser::parse_for_loop () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "for")) + if (! (t->type == tok_keyword && t->content == "for")) throw parse_error ("expected 'for'"); for_loop* s = new for_loop; s->tok = t; @@ -1333,7 +1377,7 @@ for_loop* parser::parse_while_loop () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "while")) + if (! (t->type == tok_keyword && t->content == "while")) throw parse_error ("expected 'while'"); for_loop* s = new for_loop; s->tok = t; @@ -1364,7 +1408,7 @@ foreach_loop* parser::parse_foreach_loop () { const token* t = next (); - if (! (t->type == tok_identifier && t->content == "foreach")) + if (! (t->type == tok_keyword && t->content == "foreach")) throw parse_error ("expected 'foreach'"); foreach_loop* s = new foreach_loop; s->tok = t; @@ -1426,7 +1470,7 @@ parser::parse_foreach_loop () } t = next (); - if (! (t->type == tok_identifier && t->content == "in")) + if (! (t->type == tok_keyword && t->content == "in")) throw parse_error ("expected 'in'"); s->base = parse_indexable(); @@ -1672,7 +1716,7 @@ parser::parse_array_in () } t = peek (); - if (t && t->type == tok_identifier && t->content == "in") + if (t && t->type == tok_keyword && t->content == "in") { array_in *e = new array_in; e->tok = t; |