summaryrefslogtreecommitdiffstats
path: root/parse.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'parse.cxx')
-rw-r--r--parse.cxx128
1 files changed, 86 insertions, 42 deletions
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 ("<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;