summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfche <fche>2005-05-05 20:31:53 +0000
committerfche <fche>2005-05-05 20:31:53 +0000
commit829198553c89ca7f2da93559c61c04ee89079ea1 (patch)
tree2f23d20d3d6d1c4078cbb50fc8f35d323e922cde
parente3f6c9cdd804120df4ec0b0fa33c033371958f17 (diff)
downloadsystemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.tar.gz
systemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.tar.xz
systemtap-steved-829198553c89ca7f2da93559c61c04ee89079ea1.zip
* preliminaries for code generation logic
2005-05-05 Frank Ch. Eigler <fche@redhat.com> * parse.cxx (parse): Add helper methods. (lexer::scan, parse_assignment): Parse "<<<" operator. Fix assignment associativity. (parse_symbol): Permit function with empty arg list. (parse_global, parse_statement, parse_functiondecl): Expect unconsumed leading keyword. (parse_global): Don't use ";" termination. * parse.h: Corresponding changes. * staptree.cxx (binary_expression::resolve_types): Fix <<< type inference. (translator_output): Improve pretty-printing. (*): Add general visitors to statement/expression types. * staptree.h: Corresponding changes. Tweak symresolution_info fields. Add semantic_error class. * semtest.cxx: Adapt to this. * testsuite/parseok/two.stp, semok/*.stp: Adapt to syntax changes.
-rw-r--r--ChangeLog19
-rw-r--r--parse.cxx115
-rw-r--r--parse.h3
-rw-r--r--semtest.cxx13
-rw-r--r--staptree.cxx552
-rw-r--r--staptree.h201
-rwxr-xr-xtestsuite/parseok/two.stp2
-rwxr-xr-xtestsuite/semok/five.stp4
-rwxr-xr-xtestsuite/semok/four.stp2
-rwxr-xr-xtestsuite/semok/one.stp2
-rwxr-xr-xtestsuite/semok/six.stp2
-rwxr-xr-xtestsuite/semok/three.stp4
-rwxr-xr-xtestsuite/semok/two.stp2
13 files changed, 824 insertions, 97 deletions
diff --git a/ChangeLog b/ChangeLog
index 66dc61b2..4a24cc00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2005-05-05 Frank Ch. Eigler <fche@redhat.com>
+
+ * parse.cxx (parse): Add helper methods.
+ (lexer::scan, parse_assignment): Parse "<<<" operator. Fix assignment
+ associativity.
+ (parse_symbol): Permit function with empty arg list.
+ (parse_global, parse_statement, parse_functiondecl): Expect
+ unconsumed leading keyword.
+ (parse_global): Don't use ";" termination.
+ * parse.h: Corresponding changes.
+ * staptree.cxx (binary_expression::resolve_types): Fix <<<
+ type inference.
+ (translator_output): Improve pretty-printing.
+ (*): Add general visitors to statement/expression types.
+ * staptree.h: Corresponding changes. Tweak symresolution_info fields.
+ Add semantic_error class.
+ * semtest.cxx: Adapt to this.
+ * testsuite/parseok/two.stp, semok/*.stp: Adapt to syntax changes.
+
2005-03-15 Frank Ch. Eigler <fche@redhat.com>
* semtest.cxx: Print probe signatures properly.
diff --git a/parse.cxx b/parse.cxx
index 91600e25..b5881331 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -32,6 +32,22 @@ parser::~parser()
}
+stapfile*
+parser::parse (std::istream& i)
+{
+ parser p (i);
+ return p.parse ();
+}
+
+
+stapfile*
+parser::parse (const std::string& n)
+{
+ parser p (n);
+ return p.parse ();
+}
+
+
ostream&
operator << (ostream& o, const token& t)
{
@@ -257,7 +273,15 @@ lexer::scan ()
(c == ':' && c2 == ':') ||
(c == '-' && c2 == '>') ||
false) // XXX: etc.
- n->content.push_back((char) input_get ());
+ n->content.push_back ((char) input_get ());
+
+ // handle three-character operator
+ if (c == '<' && c2 == '<')
+ {
+ int c3 = input.peek ();
+ if (c3 == '<')
+ n->content.push_back ((char) input_get ());
+ }
return n;
}
@@ -291,21 +315,11 @@ parser::parse ()
empty = false;
if (t->type == tok_identifier && t->content == "probe")
- {
- next ();
- f->probes.push_back (parse_probe ());
- }
+ f->probes.push_back (parse_probe ());
else if (t->type == tok_identifier && t->content == "global")
- {
- next ();
- parse_global (f->globals);
- }
+ parse_global (f->globals);
else if (t->type == tok_identifier && t->content == "function")
- {
- next ();
- f->functions.push_back (parse_functiondecl ());
- // XXX: check for duplicate function decl
- }
+ f->functions.push_back (parse_functiondecl ());
else
throw parse_error ("expected 'probe', 'global', or 'function'");
}
@@ -345,13 +359,18 @@ parser::parse ()
probe*
parser::parse_probe ()
{
+ const token* t0 = next ();
+ if (! (t0->type == tok_identifier && t0->content == "probe"))
+ throw parse_error ("expected 'probe'");
+
probe *p = new probe;
+ p->tok = t0;
+
while (1)
{
const token *t = peek ();
if (t && t->type == tok_identifier)
{
- p->tok = t;
p->locations.push_back (parse_probe_point ());
t = peek ();
@@ -467,6 +486,10 @@ parser::parse_statement ()
void
parser::parse_global (vector <vardecl*>& globals)
{
+ const token* t0 = next ();
+ if (! (t0->type == tok_identifier && t0->content == "global"))
+ throw parse_error ("expected 'global'");
+
while (1)
{
const token* t = next ();
@@ -478,13 +501,14 @@ parser::parse_global (vector <vardecl*>& globals)
d->tok = t;
globals.push_back (d); // XXX: check for duplicates
- t = next ();
- if (t->type == tok_operator && t->content == ";")
- break;
- else if (t->type == tok_operator && t->content == ",")
- continue;
+ t = peek ();
+ if (t && t->type == tok_operator && t->content == ",")
+ {
+ next ();
+ continue;
+ }
else
- throw parse_error ("expected ';' or ','");
+ break;
}
}
@@ -492,9 +516,13 @@ parser::parse_global (vector <vardecl*>& globals)
functiondecl*
parser::parse_functiondecl ()
{
+ const token* t = next ();
+ if (! (t->type == tok_identifier && t->content == "function"))
+ throw parse_error ("expected 'function'");
+
functiondecl *fd = new functiondecl ();
- const token* t = next ();
+ t = next ();
if (! (t->type == tok_identifier))
throw parse_error ("expected identifier");
fd->name = t->content;
@@ -675,11 +703,6 @@ parser::parse_expression ()
return parse_assignment ();
}
-// XXX: in all subsequent calls to parse_expression(),
-// check whether operator priority / associativity
-// suggests that a different expression subtype parser
-// should be called instead
-
expression*
parser::parse_assignment ()
@@ -687,10 +710,10 @@ parser::parse_assignment ()
expression* op1 = parse_ternary ();
const token* t = peek ();
- // left-associative operators
- while (t && t->type == tok_operator
+ // right-associative operators
+ if (t && t->type == tok_operator
&& (t->content == "=" ||
- t->content == "<<" ||
+ t->content == "<<<" ||
t->content == "+=" ||
false)) // XXX: add /= etc.
{
@@ -701,9 +724,10 @@ parser::parse_assignment ()
e->op = t->content;
e->tok = t;
next ();
- e->right = parse_ternary ();
+ e->right = parse_expression ();
op1 = e;
- t = peek ();
+ // XXX: map assign/accumlate operators like +=, /=
+ // to ordinary assignment + nested binary_expression
}
return op1;
@@ -1056,17 +1080,24 @@ parser::parse_symbol ()
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 == ")")
+ {
+ next ();
+ return f;
+ }
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;
- else
- throw parse_error ("expected ',' or ')'");
- }
+ {
+ f->args.push_back (parse_expression ());
+ t = next ();
+ if (t->type == tok_operator && t->content == ")")
+ break;
+ if (t->type == tok_operator && t->content == ",")
+ continue;
+ else
+ throw parse_error ("expected ',' or ')'");
+ }
return f;
}
else
diff --git a/parse.h b/parse.h
index f2510d7e..1d07645f 100644
--- a/parse.h
+++ b/parse.h
@@ -64,6 +64,9 @@ public:
stapfile* parse ();
+ static stapfile* parse (std::istream& i);
+ static stapfile* parse (const std::string& n);
+
private:
std::string input_name;
std::istream* free_input;
diff --git a/semtest.cxx b/semtest.cxx
index a37e3323..09cd7576 100644
--- a/semtest.cxx
+++ b/semtest.cxx
@@ -21,7 +21,7 @@ semantic_pass_1 (vector<stapfile*>& files)
for (unsigned j=0; j<f->functions.size(); j++)
{
functiondecl* fn = f->functions[j];
- symresolution_info ri (fn->locals, f->globals, files, f, fn);
+ symresolution_info ri (fn->locals, f->globals, f->functions, fn);
fn->body->resolve_symbols (ri);
if (ri.num_unresolved)
@@ -32,7 +32,7 @@ semantic_pass_1 (vector<stapfile*>& files)
for (unsigned j=0; j<f->probes.size(); j++)
{
probe* pn = f->probes[j];
- symresolution_info ri (pn->locals, f->globals, files, f);
+ symresolution_info ri (pn->locals, f->globals, f->functions);
pn->body->resolve_symbols (ri);
if (ri.num_unresolved)
@@ -113,8 +113,7 @@ main (int argc, char *argv [])
vector<stapfile*> files;
if (argc == 1)
{
- parser p (cin);
- stapfile* f = p.parse ();
+ stapfile* f = parser::parse (cin);
if (f)
files.push_back (f);
else
@@ -122,8 +121,7 @@ main (int argc, char *argv [])
}
else for (int i = 1; i < argc; i ++)
{
- parser p (argv[i]);
- stapfile* f = p.parse ();
+ stapfile* f = parser::parse (argv[i]);
if (f)
files.push_back (f);
else
@@ -131,7 +129,8 @@ main (int argc, char *argv [])
}
rc += semantic_pass_1 (files);
- rc += semantic_pass_2 (files);
+ if (rc == 0)
+ rc += semantic_pass_2 (files);
for (unsigned i=0; i<files.size(); i++)
{
diff --git a/staptree.cxx b/staptree.cxx
index 34242c8f..ab2ebb97 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -62,7 +62,13 @@ symboldecl::~symboldecl ()
probe_point::probe_point ():
- tok (0), prov (0)
+ tok (0)
+{
+}
+
+
+probe::probe ():
+ body (0), tok (0)
{
}
@@ -342,6 +348,13 @@ void probe_point::print (ostream& o)
}
+ostream& operator << (ostream& o, probe_point& k)
+{
+ k.print (o);
+ return o;
+}
+
+
ostream& operator << (ostream& o, symboldecl& k)
{
k.print (o);
@@ -355,9 +368,8 @@ ostream& operator << (ostream& o, symboldecl& k)
symresolution_info::symresolution_info (vector<vardecl*>& l,
vector<vardecl*>& g,
- vector<stapfile*>& f,
- stapfile* tf):
- locals (l), globals (g), files (f), current_file (tf), current_function (0)
+ vector<functiondecl*>& f):
+ locals (l), globals (g), functions (f), current_function (0)
{
num_unresolved = 0;
}
@@ -365,10 +377,9 @@ symresolution_info::symresolution_info (vector<vardecl*>& l,
symresolution_info::symresolution_info (vector<vardecl*>& l,
vector<vardecl*>& g,
- vector<stapfile*>& f,
- stapfile* tf,
+ vector<functiondecl*>& f,
functiondecl* cf):
- locals (l), globals (g), files (f), current_file (tf), current_function (cf)
+ locals (l), globals (g), functions (f), current_function (cf)
{
num_unresolved = 0;
}
@@ -576,9 +587,9 @@ functiondecl*
symresolution_info::find_function (const string& name,
const vector<expression*>& args)
{
- for (unsigned j = 0; j < current_file->functions.size(); j++)
+ for (unsigned j = 0; j < functions.size(); j++)
{
- functiondecl* fd = current_file->functions[j];
+ functiondecl* fd = functions[j];
if (fd->name == name)
return fd;
}
@@ -621,15 +632,15 @@ literal::resolve_types (typeresolution_info& r, exp_type t)
void
binary_expression::resolve_types (typeresolution_info& r, exp_type t)
{
- if (op == "<<")
+ if (op == "<<<") // stats aggregation
{
left->resolve_types (r, pe_stats);
right->resolve_types (r, pe_long);
- if (t == pe_long || t == pe_string)
- r.mismatch (tok, t, pe_stats);
+ if (t == pe_stats || t == pe_string)
+ r.mismatch (tok, t, pe_long);
else if (type == pe_unknown)
{
- type = pe_stats;
+ type = pe_long;
r.resolved (tok, type);
}
}
@@ -645,7 +656,9 @@ binary_expression::resolve_types (typeresolution_info& r, exp_type t)
r.resolved (tok, type);
}
}
- else if (op == "==") // XXX: other comparison operators
+ else if (op == "=="
+ || op == "in" // XXX: really a unary operator
+ || false) // XXX: other comparison operators
{
left->resolve_types (r, pe_unknown);
right->resolve_types (r, pe_unknown);
@@ -977,26 +990,519 @@ typeresolution_info::resolved (const token* tok, exp_type t)
// ------------------------------------------------------------------------
-// semantic processing: lvalue checking
+// semantic processing: lvalue checking: XXX: unneeded?
+
bool
-pre_crement::is_lvalue ()
+assignment::is_lvalue ()
{
- return operand->is_lvalue ();
+ return left->is_lvalue ();
}
-bool
-post_crement::is_lvalue ()
+// ------------------------------------------------------------------------
+// unparser
+
+
+translator_output::translator_output (ostream& f):
+ o (f), tablevel (0)
{
- return operand->is_lvalue ();
}
-bool
-assignment::is_lvalue ()
+ostream&
+translator_output::newline (int indent)
{
- return left->is_lvalue ();
+ assert (indent > 0 || tablevel >= (unsigned)-indent);
+ tablevel += indent;
+ o << endl;
+ for (unsigned i=0; i<tablevel; i++)
+ o << " ";
+ return o;
+}
+
+
+void
+translator_output::indent (int indent)
+{
+ assert (indent > 0 || tablevel >= (unsigned)-indent);
+ tablevel += indent;
+}
+
+
+ostream&
+translator_output::line ()
+{
+ return o;
+}
+
+
+
+// ------------------------------------------------------------------------
+// visitors
+
+
+void
+block::visit (visitor* u)
+{
+ u->visit_block (this);
+}
+
+void
+for_loop::visit (visitor* u)
+{
+ u->visit_for_loop (this);
+}
+
+void
+null_statement::visit (visitor* u)
+{
+ u->visit_null_statement (this);
+}
+
+void
+expr_statement::visit (visitor* u)
+{
+ u->visit_expr_statement (this);
+}
+
+void
+return_statement::visit (visitor* u)
+{
+ u->visit_return_statement (this);
+}
+
+void
+delete_statement::visit (visitor* u)
+{
+ u->visit_delete_statement (this);
+}
+
+void
+if_statement::visit (visitor* u)
+{
+ u->visit_if_statement (this);
+}
+
+void
+literal_string::visit(visitor* u)
+{
+ u->visit_literal_string (this);
+}
+
+void
+literal_number::visit(visitor* u)
+{
+ u->visit_literal_number (this);
+}
+
+void
+binary_expression::visit (visitor* u)
+{
+ u->visit_binary_expression (this);
+}
+
+void
+unary_expression::visit (visitor* u)
+{
+ u->visit_unary_expression (this);
+}
+
+void
+pre_crement::visit (visitor* u)
+{
+ u->visit_pre_crement (this);
+}
+
+void
+post_crement::visit (visitor* u)
+{
+ u->visit_post_crement (this);
+}
+
+void
+logical_or_expr::visit (visitor* u)
+{
+ u->visit_logical_or_expr (this);
+}
+
+void
+logical_and_expr::visit (visitor* u)
+{
+ u->visit_logical_and_expr (this);
+}
+
+void
+array_in::visit (visitor* u)
+{
+ u->visit_array_in (this);
+}
+
+void
+comparison::visit (visitor* u)
+{
+ u->visit_comparison (this);
+}
+
+void
+concatenation::visit (visitor* u)
+{
+ u->visit_concatenation (this);
+}
+
+void
+exponentiation::visit (visitor* u)
+{
+ u->visit_exponentiation (this);
+}
+
+void
+ternary_expression::visit (visitor* u)
+{
+ u->visit_ternary_expression (this);
+}
+
+void
+assignment::visit (visitor* u)
+{
+ u->visit_assignment (this);
+}
+
+void
+symbol::visit (visitor* u)
+{
+ u->visit_symbol (this);
+}
+
+void
+arrayindex::visit (visitor* u)
+{
+ u->visit_arrayindex (this);
+}
+
+void
+functioncall::visit (visitor* u)
+{
+ u->visit_functioncall (this);
+}
+
+
+// ------------------------------------------------------------------------
+
+void
+traversing_visitor::visit_block (block *s)
+{
+ for (unsigned i=0; i<s->statements.size(); i++)
+ s->statements[i]->visit (this);
+}
+
+void
+traversing_visitor::visit_null_statement (null_statement *s)
+{
+}
+
+void
+traversing_visitor::visit_expr_statement (expr_statement *s)
+{
+ s->value->visit (this);
+}
+
+void
+traversing_visitor::visit_if_statement (if_statement* s)
+{
+ s->condition->visit (this);
+ s->thenblock->visit (this);
+ s->elseblock->visit (this);
+}
+
+void
+traversing_visitor::visit_for_loop (for_loop* s)
+{
+ s->init->visit (this);
+ s->cond->visit (this);
+ s->incr->visit (this);
+ s->block->visit (this);
+}
+
+void
+traversing_visitor::visit_return_statement (return_statement* s)
+{
+ s->value->visit (this);
+}
+
+void
+traversing_visitor::visit_delete_statement (delete_statement* s)
+{
+ s->value->visit (this);
+}
+
+void
+traversing_visitor::visit_literal_string (literal_string* e)
+{
+}
+
+void
+traversing_visitor::visit_literal_number (literal_number* e)
+{
+}
+
+void
+traversing_visitor::visit_binary_expression (binary_expression* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_unary_expression (unary_expression* e)
+{
+ e->operand->visit (this);
+}
+
+void
+traversing_visitor::visit_pre_crement (pre_crement* e)
+{
+ e->operand->visit (this);
+}
+
+void
+traversing_visitor::visit_post_crement (post_crement* e)
+{
+ e->operand->visit (this);
+}
+
+
+void
+traversing_visitor::visit_logical_or_expr (logical_or_expr* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_logical_and_expr (logical_and_expr* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_array_in (array_in* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_comparison (comparison* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_concatenation (concatenation* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_exponentiation (exponentiation* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_ternary_expression (ternary_expression* e)
+{
+ e->cond->visit (this);
+ e->truevalue->visit (this);
+ e->falsevalue->visit (this);
+}
+
+void
+traversing_visitor::visit_assignment (assignment* e)
+{
+ e->left->visit (this);
+ e->right->visit (this);
+}
+
+void
+traversing_visitor::visit_symbol (symbol* e)
+{
+}
+
+void
+traversing_visitor::visit_arrayindex (arrayindex* e)
+{
+ for (unsigned i=0; i<e->indexes.size(); i++)
+ e->indexes[i]->visit (this);
+}
+
+void
+traversing_visitor::visit_functioncall (functioncall* e)
+{
+ for (unsigned i=0; i<e->args.size(); i++)
+ e->args[i]->visit (this);
+}
+
+
+// ------------------------------------------------------------------------
+
+
+throwing_visitor::throwing_visitor (const std::string& m): msg (m) {}
+throwing_visitor::throwing_visitor (): msg ("invalid element") {}
+
+
+void
+throwing_visitor::throwone (const token* t)
+{
+ throw semantic_error (msg, t);
+}
+
+void
+throwing_visitor::visit_block (block *s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_null_statement (null_statement *s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_expr_statement (expr_statement *s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_if_statement (if_statement* s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_for_loop (for_loop* s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_return_statement (return_statement* s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_delete_statement (delete_statement* s)
+{
+ throwone (s->tok);
+}
+
+void
+throwing_visitor::visit_literal_string (literal_string* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_literal_number (literal_number* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_binary_expression (binary_expression* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_unary_expression (unary_expression* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_pre_crement (pre_crement* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_post_crement (post_crement* e)
+{
+ throwone (e->tok);
}
+void
+throwing_visitor::visit_logical_or_expr (logical_or_expr* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_logical_and_expr (logical_and_expr* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_array_in (array_in* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_comparison (comparison* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_concatenation (concatenation* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_exponentiation (exponentiation* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_ternary_expression (ternary_expression* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_assignment (assignment* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_symbol (symbol* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_arrayindex (arrayindex* e)
+{
+ throwone (e->tok);
+}
+
+void
+throwing_visitor::visit_functioncall (functioncall* e)
+{
+ throwone (e->tok);
+}
diff --git a/staptree.h b/staptree.h
index b28a334b..82b95292 100644
--- a/staptree.h
+++ b/staptree.h
@@ -2,14 +2,38 @@
// Copyright 2005 Red Hat Inc.
// GPL
+#ifndef STAPTREE_H
+#define STAPTREE_H
+
#include <string>
#include <vector>
#include <map>
#include <iostream>
+#include <stdexcept>
+
using namespace std;
+struct token; // parse.h
+struct semantic_error: public std::runtime_error
+{
+ const token* tok1;
+ const string msg2;
+ const token* tok2;
+
+ ~semantic_error () throw () {}
+ semantic_error (const string& msg):
+ runtime_error (msg), tok1 (0), tok2 (0) {}
+ semantic_error (const string& msg, const token* t1):
+ runtime_error (msg), tok1 (t1), tok2 (0) {}
+ semantic_error (const string& msg, const token* t1,
+ const string& m2, const token* t2):
+ runtime_error (msg), tok1 (t1), msg2 (m2), tok2 (t2) {}
+};
+
+
+
enum exp_type
{
pe_unknown,
@@ -23,16 +47,19 @@ ostream& operator << (ostream& o, const exp_type& e);
struct token;
struct symresolution_info;
struct typeresolution_info;
+struct visitor;
+
struct expression
{
exp_type type;
const token* tok;
- virtual void print (ostream& o) = 0;
expression ();
virtual ~expression ();
+ virtual void print (ostream& o) = 0;
virtual void resolve_symbols (symresolution_info& r) = 0;
virtual void resolve_types (typeresolution_info& r, exp_type t) = 0;
- virtual bool is_lvalue () = 0;
+ virtual bool is_lvalue () = 0; // XXX: deprecate
+ virtual void visit (visitor* u) = 0;
};
ostream& operator << (ostream& o, expression& k);
@@ -51,6 +78,7 @@ struct literal_string: public literal
string value;
literal_string (const string& v);
void print (ostream& o);
+ void visit (visitor* u);
};
@@ -59,6 +87,7 @@ struct literal_number: public literal
long value;
literal_number (long v);
void print (ostream& o);
+ void visit (visitor* u);
};
@@ -68,6 +97,7 @@ struct binary_expression: public expression
string op;
expression* right;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return false; }
@@ -79,6 +109,7 @@ struct unary_expression: public expression
string op;
expression* operand;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return false; }
@@ -87,44 +118,50 @@ struct unary_expression: public expression
struct pre_crement: public unary_expression
{
- bool is_lvalue ();
+ void visit (visitor* u);
};
struct post_crement: public unary_expression
{
- bool is_lvalue ();
void print (ostream& o);
+ void visit (visitor* u);
};
struct logical_or_expr: public binary_expression
{
+ void visit (visitor* u);
};
struct logical_and_expr: public binary_expression
{
+ void visit (visitor* u);
};
struct array_in: public binary_expression
{
+ void visit (visitor* u);
};
struct comparison: public binary_expression
{
+ void visit (visitor* u);
};
struct concatenation: public binary_expression
{
+ void visit (visitor* u);
};
struct exponentiation: public binary_expression
{
+ void visit (visitor* u);
};
@@ -134,6 +171,7 @@ struct ternary_expression: public expression
expression* truevalue;
expression* falsevalue;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return false; }
@@ -143,6 +181,7 @@ struct ternary_expression: public expression
struct assignment: public binary_expression
{
bool is_lvalue ();
+ void visit (visitor* u);
};
@@ -153,6 +192,7 @@ struct symbol: public expression
vardecl *referent;
symbol ();
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return true; }
@@ -166,6 +206,7 @@ struct arrayindex: public expression
vardecl *referent;
arrayindex ();
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return true; }
@@ -180,6 +221,7 @@ struct functioncall: public expression
functiondecl *referent;
functioncall ();
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r, exp_type t);
bool is_lvalue () { return false; }
@@ -195,19 +237,16 @@ struct symresolution_info
{
vector<vardecl*>& locals; // includes incoming function parameters
vector<vardecl*>& globals;
- vector<stapfile*>& files;
- stapfile* current_file;
+ vector<functiondecl*>& functions;
functiondecl* current_function;
symresolution_info (vector<vardecl*>& l,
vector<vardecl*>& g,
- vector<stapfile*>& f,
- stapfile* cfil,
+ vector<functiondecl*>& f,
functiondecl* cfun);
symresolution_info (vector<vardecl*>& l,
vector<vardecl*>& g,
- vector<stapfile*>& f,
- stapfile* cfil);
+ vector<functiondecl*>& f);
vardecl* find_scalar (const string& name);
vardecl* find_array (const string& name, const vector<expression*>&);
@@ -225,8 +264,7 @@ struct typeresolution_info
bool assert_resolvability;
functiondecl* current_function;
- void mismatch (const token* tok, exp_type t1,
- exp_type t2);
+ void mismatch (const token* tok, exp_type t1, exp_type t2);
void unresolved (const token* tok);
void resolved (const token* tok, exp_type t);
void invalid (const token* tok, exp_type t);
@@ -282,6 +320,7 @@ struct functiondecl: public symboldecl
struct statement
{
virtual void print (ostream& o) = 0;
+ virtual void visit (visitor* u) = 0;
const token* tok;
statement ();
virtual ~statement ();
@@ -296,6 +335,7 @@ struct block: public statement
{
vector<statement*> statements;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r);
};
@@ -307,6 +347,7 @@ struct for_loop: public statement
expression* incr;
statement* block;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r);
};
@@ -315,6 +356,7 @@ struct for_loop: public statement
struct null_statement: public statement
{
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r) {}
void resolve_types (typeresolution_info& r) {}
};
@@ -324,6 +366,7 @@ struct expr_statement: public statement
{
expression* value; // executed for side-effects
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r);
};
@@ -335,6 +378,7 @@ struct if_statement: public statement
statement* thenblock;
statement* elseblock;
void print (ostream& o);
+ void visit (visitor* u);
void resolve_symbols (symresolution_info& r);
void resolve_types (typeresolution_info& r);
};
@@ -343,6 +387,7 @@ struct if_statement: public statement
struct return_statement: public expr_statement
{
void print (ostream& o);
+ void visit (visitor* u);
void resolve_types (typeresolution_info& r);
};
@@ -350,6 +395,7 @@ struct return_statement: public expr_statement
struct delete_statement: public expr_statement
{
void print (ostream& o);
+ void visit (visitor* u);
};
@@ -364,29 +410,152 @@ struct stapfile
};
-class provider;
struct probe_point
{
struct component // XXX: sort of a restricted functioncall
{
string functor;
- literal* arg;
+ literal* arg; // optional
component ();
};
vector<component*> components;
const token* tok; // points to first component's functor
- provider* prov;
void print (ostream& o);
probe_point ();
};
+ostream& operator << (ostream& o, probe_point& k);
+
struct probe
{
vector<probe_point*> locations;
- const token* tok;
block* body;
+ const token* tok;
vector<vardecl*> locals;
+ probe ();
void print (ostream& o);
void printsig (ostream &o);
};
+
+
+
+// Output context for systemtap translation, intended to allow
+// pretty-printing.
+class translator_output
+{
+ ostream& o;
+ unsigned tablevel;
+
+public:
+ translator_output (ostream& file);
+
+ ostream& newline (int indent = 0);
+ void indent (int indent = 0);
+ ostream& line();
+};
+
+
+// An derived visitor instance is used to visit the entire
+// statement/expression tree.
+struct visitor
+{
+ virtual ~visitor () {}
+ virtual void visit_block (block *s) = 0;
+ virtual void visit_null_statement (null_statement *s) = 0;
+ virtual void visit_expr_statement (expr_statement *s) = 0;
+ virtual void visit_if_statement (if_statement* s) = 0;
+ virtual void visit_for_loop (for_loop* s) = 0;
+ virtual void visit_return_statement (return_statement* s) = 0;
+ virtual void visit_delete_statement (delete_statement* s) = 0;
+ virtual void visit_literal_string (literal_string* e) = 0;
+ virtual void visit_literal_number (literal_number* e) = 0;
+ virtual void visit_binary_expression (binary_expression* e) = 0;
+ virtual void visit_unary_expression (unary_expression* e) = 0;
+ virtual void visit_pre_crement (pre_crement* e) = 0;
+ virtual void visit_post_crement (post_crement* e) = 0;
+ virtual void visit_logical_or_expr (logical_or_expr* e) = 0;
+ virtual void visit_logical_and_expr (logical_and_expr* e) = 0;
+ virtual void visit_array_in (array_in* e) = 0;
+ virtual void visit_comparison (comparison* e) = 0;
+ virtual void visit_concatenation (concatenation* e) = 0;
+ virtual void visit_exponentiation (exponentiation* e) = 0;
+ virtual void visit_ternary_expression (ternary_expression* e) = 0;
+ virtual void visit_assignment (assignment* e) = 0;
+ virtual void visit_symbol (symbol* e) = 0;
+ virtual void visit_arrayindex (arrayindex* e) = 0;
+ virtual void visit_functioncall (functioncall* e) = 0;
+};
+
+
+// A default kind of visitor, which by default travels down
+// to the leaves of the statement/expression tree, up to
+// but excluding following vardecls (referent pointers).
+struct traversing_visitor: public visitor
+{
+ void visit_block (block *s);
+ void visit_null_statement (null_statement *s);
+ void visit_expr_statement (expr_statement *s);
+ void visit_if_statement (if_statement* s);
+ void visit_for_loop (for_loop* s);
+ void visit_return_statement (return_statement* s);
+ void visit_delete_statement (delete_statement* s);
+ void visit_literal_string (literal_string* e);
+ void visit_literal_number (literal_number* e);
+ void visit_binary_expression (binary_expression* e);
+ void visit_unary_expression (unary_expression* e);
+ void visit_pre_crement (pre_crement* e);
+ void visit_post_crement (post_crement* e);
+ void visit_logical_or_expr (logical_or_expr* e);
+ void visit_logical_and_expr (logical_and_expr* e);
+ void visit_array_in (array_in* e);
+ void visit_comparison (comparison* e);
+ void visit_concatenation (concatenation* e);
+ void visit_exponentiation (exponentiation* e);
+ void visit_ternary_expression (ternary_expression* e);
+ void visit_assignment (assignment* e);
+ void visit_symbol (symbol* e);
+ void visit_arrayindex (arrayindex* e);
+ void visit_functioncall (functioncall* e);
+};
+
+
+// A kind of visitor that throws an semantic_error exception
+// whenever a non-overridden method is called.
+struct throwing_visitor: public visitor
+{
+ std::string msg;
+ throwing_visitor (const std::string& m);
+ throwing_visitor ();
+
+ virtual void throwone (const token* t);
+
+ void visit_block (block *s);
+ void visit_null_statement (null_statement *s);
+ void visit_expr_statement (expr_statement *s);
+ void visit_if_statement (if_statement* s);
+ void visit_for_loop (for_loop* s);
+ void visit_return_statement (return_statement* s);
+ void visit_delete_statement (delete_statement* s);
+ void visit_literal_string (literal_string* e);
+ void visit_literal_number (literal_number* e);
+ void visit_binary_expression (binary_expression* e);
+ void visit_unary_expression (unary_expression* e);
+ void visit_pre_crement (pre_crement* e);
+ void visit_post_crement (post_crement* e);
+ void visit_logical_or_expr (logical_or_expr* e);
+ void visit_logical_and_expr (logical_and_expr* e);
+ void visit_array_in (array_in* e);
+ void visit_comparison (comparison* e);
+ void visit_concatenation (concatenation* e);
+ void visit_exponentiation (exponentiation* e);
+ void visit_ternary_expression (ternary_expression* e);
+ void visit_assignment (assignment* e);
+ void visit_symbol (symbol* e);
+ void visit_arrayindex (arrayindex* e);
+ void visit_functioncall (functioncall* e);
+};
+
+
+
+#endif // STAPTREE_H
diff --git a/testsuite/parseok/two.stp b/testsuite/parseok/two.stp
index b6b843de..fdcf335e 100755
--- a/testsuite/parseok/two.stp
+++ b/testsuite/parseok/two.stp
@@ -2,7 +2,7 @@
probe syscall (231)
{
- array[idx] << value;
+ array[idx] <<< value;
if (global > 5) { global -- } else ;
}
diff --git a/testsuite/semok/five.stp b/testsuite/semok/five.stp
index c8b59e73..2bb656b1 100755
--- a/testsuite/semok/five.stp
+++ b/testsuite/semok/five.stp
@@ -1,7 +1,7 @@
-#! parsetest
+#! semtest
probe foo
{
array[1] = array[2] = 3;
- statvar << value << 4;
+ statvar <<< value <<< 4;
}
diff --git a/testsuite/semok/four.stp b/testsuite/semok/four.stp
index c3b2a7d0..eb87f3f9 100755
--- a/testsuite/semok/four.stp
+++ b/testsuite/semok/four.stp
@@ -2,7 +2,7 @@
# these will ultimately be somehow associated with "providers"
# and have a syntax of their own
-global kernel_jiffies, kernel_current_comm;
+global kernel_jiffies, kernel_current_comm
function kernel_netlink(a, b) {
# this should be a builtin function
diff --git a/testsuite/semok/one.stp b/testsuite/semok/one.stp
index 336e57d2..764bd476 100755
--- a/testsuite/semok/one.stp
+++ b/testsuite/semok/one.stp
@@ -2,7 +2,7 @@
# these will ultimately be somehow associated with "providers"
# and have a syntax of their own
-global kernel_jiffies, kernel_current_comm;
+global kernel_jiffies, kernel_current_comm
function kernel_netlink(a, b) {
# this should be a builtin function
diff --git a/testsuite/semok/six.stp b/testsuite/semok/six.stp
index 53d69503..72b7e065 100755
--- a/testsuite/semok/six.stp
+++ b/testsuite/semok/six.stp
@@ -1,4 +1,4 @@
-#! parsetest
+#! semtest
probe foo
{
diff --git a/testsuite/semok/three.stp b/testsuite/semok/three.stp
index 6ae531a2..100a5f2b 100755
--- a/testsuite/semok/three.stp
+++ b/testsuite/semok/three.stp
@@ -1,6 +1,6 @@
#! semtest
probe foo {
- a << 2;
- b[4] << 4;
+ a <<< 2;
+ b[4] <<< 4;
}
diff --git a/testsuite/semok/two.stp b/testsuite/semok/two.stp
index f3c6046e..5a124474 100755
--- a/testsuite/semok/two.stp
+++ b/testsuite/semok/two.stp
@@ -1,6 +1,6 @@
#! semtest
-global bar, baz;
+global bar, baz
function koo (p) {
baz [p, "p", p] ++;