From 6e213f58c493be12eeb4f1532da3891c7baafbd5 Mon Sep 17 00:00:00 2001 From: dsmith Date: Tue, 16 May 2006 18:51:34 +0000 Subject: 2006-05-16 David Smith * 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. --- parse.cxx | 128 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 42 deletions(-) (limited to 'parse.cxx') diff --git a/parse.cxx b/parse.cxx index 0eba81bb..9a3f2d43 100644 --- a/parse.cxx +++ b/parse.cxx @@ -30,14 +30,14 @@ parser::parser (systemtap_session& s, istream& i, bool p): session (s), input_name (""), 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; icontent = 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_ret, std::vector & 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 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 & 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& 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) 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& 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; -- cgit