This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: semantic error: cannot expand unknown type


On Fri, 2006-05-12 at 18:43 -0400, Frank Ch. Eigler wrote:
> Hi -
> 
> dsmith wrote:
> 
> > [...]  Yeah, it is a bit ugly.  However, if we don't explicitly only
> > take "return" and "function" here, then the user is free to write
> > 'probe kernel.while("sys_read").if'.
> 
> I'd be OK with that.  We can keep a separate namespace for probe
> points.

OK.  I've allowed all keywords there.

> > [...]
> > >We should outlaw the latter two (and rename or remove the current
> > >string() function in conversions.stp).
> > >
> > Glad we agree.  What do we want to rename the string() function to?  
> > ltoa()? long2str()? long_to_string()?  Or something else?  I'd probably 
> > pick "long_to_string()".
> 
> Or just remove it altogether: sprint(<numeric-expression>) is equivalent.

True.  What about the hexstring() function in conversions.stp (which
also calls sprintf)?

> 
> > [...]
> > if (!(ok)) return (value) = (retval())
> > When the parser sees the return, it isn't smart enough to realize that a 
> > return keyword isn't valid in a probe point, only in a function.
> 
> Yes, and similarly with "next".  Detecting the wrong "escape"
> statement is left to translation time.  One could fix the parser in a
> couple of little ways:
> - parametrize the statement parsers, passing along a "in_function_p" flag
>   that originates from from parse_functiondecl() and parse_probe()
> - or pass the equivalent flag within a parser class member variable
> - or fork the parse_stmt_block and parse_statement
> 
> The first and second of these seem okay, only slightly noxious.
> The third has a theorist's respect and an engineer's disdain.  :-)
> 
> - FChE

I took the second route.  See the attached patch.

-- 
David Smith
dsmith@redhat.com
Red Hat, Inc.
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)

Index: parse.cxx
===================================================================
RCS file: /cvs/systemtap/src/parse.cxx,v
retrieving revision 1.45
diff -u -p -r1.45 parse.cxx
--- parse.cxx	9 May 2006 12:55:57 -0000	1.45
+++ parse.cxx	15 May 2006 17:16:49 -0000
@@ -30,14 +30,14 @@ parser::parser (systemtap_session& s, is
   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 *
 		     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<
   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<
       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;
Index: parse.h
===================================================================
RCS file: /cvs/systemtap/src/parse.h,v
retrieving revision 1.20
diff -u -p -r1.20 parse.h
--- parse.h	9 May 2006 12:55:57 -0000	1.20
+++ parse.h	15 May 2006 15:39:30 -0000
@@ -29,8 +29,13 @@ std::ostream& operator << (std::ostream&
 enum token_type 
   {
     tok_junk, tok_identifier, tok_operator, tok_string, tok_number,
-    tok_embedded
-    // XXX: add tok_keyword throughout
+    tok_embedded, tok_keyword
+  };
+
+
+enum parse_context
+  {
+    con_unknown, con_probe, con_global, con_function, con_embedded
   };
 
 
@@ -90,6 +95,7 @@ private:
   std::istream* free_input;
   lexer input;
   bool privileged;
+  parse_context context;
 
   // preprocessing subordinate
   std::vector<const token*> enqueued_pp;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]