lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> writes:

> >If anyone knows how to recognize the table constructor
> >syntax in YACC, please let me know.
> 
> You might want to look at Lua 3.0 and previous versions of Lua. They
> included lua.stx, a yacc file for the parser. Of course, the
> language has changed since then, but perhaps the table constructor
> code is still valid.

The table grammar in lua.stx was very helpful, but slightly wrong.  It
forced all list style field specifications to precede all assignment
style field specifications.  The fix was easy, and the patch is
enclosed.

> >After looking at the 4.1 alpha manual and then viewing the source
> >code, I realized that the section giving the complete syntax of Lua is
> >no longer valid.
> 
> I'm sorry about this. The syntax in the body of the manual should be
> correct.  The summary at the end might not be consistent with the
> main body.

So the idea is that, for expository purposes, an ambiguous grammar
will be annotated with notes saying that certain expressions must
evaluate to values of a specified type.  Sounds like a plan.

I noticed that certain erroneous programs are accepted by the Lua
compiler, but rejected by lsc.  

bash-2.01$ luac -v
Lua 4.1 (alpha)  Copyright (C) 1994-2001 TeCGraf, PUC-Rio
bash-2.01$ cat funcall.lua 
(name)(0)  -- good
bash-2.01$ ./lsc funcall.lua 
bash-2.01$ luac funcall.lua 
bash-2.01$ cat tablecall.lua
({})(0)    -- bad
bash-2.01$ ./lsc tablecall.lua
tablecall.lua:1:6: cannot apply a table
error during parse
bash-2.01$ luac tablecall.lua
bash-2.01$ cat nilcall.lua 
nil(0)     -- bad
bash-2.01$ ./lsc nilcall.lua 
nilcall.lua:1:3: parse error
error during parse
bash-2.01$ luac nilcall.lua 
bash-2.01$ 

I think most of these errors could be easily detected by the Lua
compiler, by changing the C function that recognizes expressions.

John

--- lsc.lua-l.y	Wed Aug  8 07:30:41 2001
+++ lsc.y	Wed Aug  8 08:06:47 2001
@@ -1,8 +1,6 @@
 %{
 
-/* Lua Syntax Checker -- Well an try at one...
-   This version does not parse numbers 
-   or table constructors correctly. 
+/* Lua Syntax Checker
 
    John D. Ramsdell -- August 2001
 */
@@ -54,6 +52,8 @@
   fprintf(stderr, "%s:%d:%d: %s\n", filename, line, column, s);
 }
 
+int yylex();
+
 %}
 
 %start block
@@ -168,9 +168,14 @@
   | COMMA ELIPSES;
 
 assignment:
-    /* Empty */ { if ($0 != CALL) YYERROR; } %prec NONARG
-  | ASSIGN { if ($0 != LOCATION) YYERROR; } expression_list 
-  | COMMA { if ($0 != LOCATION) YYERROR; } 
+    /* Empty */ 
+      { if ($0 != CALL) { yyerror("expecting at call"); YYERROR; } } 
+      %prec NONARG
+  | ASSIGN 
+      { if ($0 != LOCATION) { yyerror("expecting a location"); YYERROR; } }
+      expression_list 
+  | COMMA
+      { if ($0 != LOCATION) { yyerror("expecting a location"); YYERROR; } }
       location_list ASSIGN expression_list;
   
 location_list:
@@ -178,7 +183,8 @@
   | location_list COMMA location;
 
 location:
-    primary rest { if ($2 != LOCATION) YYERROR; };
+    primary rest
+      { if ($2 != LOCATION) { yyerror("expecting a location"); YYERROR; } };
 
 optional_elseif_list:
     /* Empty */
@@ -252,13 +258,17 @@
 rest:
     /* Empty */ { $$ = $0; }
   | rest PERIOD key
-    { if ($0 == CLOSURE) YYERROR; $$ = LOCATION; }
+      { if ($0 == CLOSURE) { yyerror("cannot index a closure"); YYERROR; }
+        $$ = LOCATION; }
   | rest LBRACKET expression RBRACKET 
-    { if ($0 == CLOSURE) YYERROR; $$ = LOCATION; }
+      { if ($0 == CLOSURE) { yyerror("cannot index a closure"); YYERROR; }
+        $$ = LOCATION; }
   | rest COLON key args 
-    { if ($0 == CLOSURE) YYERROR; $$ = CALL;}
+      { if ($0 == CLOSURE) { yyerror("cannot index a closure"); YYERROR; }
+        $$ = LOCATION; }
   | rest args 
-    { if ($0 == TABLE) YYERROR; $$ = CALL;};
+      { if ($0 == TABLE) { yyerror("cannot apply a table"); YYERROR; }
+        $$ = LOCATION; };
 
 args:
     LPAR optional_expression_list RPAR
@@ -269,17 +279,30 @@
     LBRACE table_contents RBRACE;
 
 table_contents: 
-    optional_table_pair_list optional_table_item_list;
+    optional_list_field_list optional_semicolon_binding_field_list;
+  | binding_field_list optional_comma optional_semicolon_list_field_list;
+
+optional_list_field_list:
+    /* Empty */
+  | expression_list optional_comma;
+
+optional_semicolon_list_field_list:
+    /* Empty */
+  | SEMICOLON optional_list_field_list;
+
+optional_semicolon_binding_field_list:
+    /* Empty */
+  | SEMICOLON optional_binding_field_list;
 
-optional_table_pair_list:
+optional_binding_field_list:
     /* Empty */
-  | table_pair_list optional_comma; 
+  | binding_field_list optional_comma; 
 
-table_pair_list:
-    table_pair
-  | table_pair_list COMMA table_pair;
+binding_field_list:
+    binding_field
+  | binding_field_list COMMA binding_field;
 
-table_pair:
+binding_field:
     LBRACKET expression RBRACKET ASSIGN expression
   | key ASSIGN expression;
 
@@ -287,14 +310,6 @@
     /* Empty */
   | COMMA;
 
-optional_table_item_list:
-    /* Empty */
-  | SEMICOLON optional_table_item_list2 optional_comma;
-
-optional_table_item_list2:
-    /* Empty */
-  | optional_table_item_list2 COMMA expression;
-
 %%
 
 static int pushed = 0;
@@ -343,7 +358,7 @@
     if (ch == delim)
       return;
     if (ch == EOF) {
-      yyerror("End of file in a string");
+      yyerror("end of file in a string");
       exit(1);
     }
     if (ch == '\\') {
@@ -539,6 +554,7 @@
 	  }
 	  name[i] = ch;
 	}
+	name[MAX_NAME - 1] = 0;
 	yyerror("Name too large");
 	exit(1);
 	return NAME;
@@ -561,18 +577,34 @@
     case '7':
     case '8':
     case '9':
-      /* Numbers must be integers or decimals for now. */
       while (1) {
 	ch = getch();
 	if (ch == '.') {
-	  while (1) {
-	    ch = getch();
-	    if (!isdigit(ch)) {
-	      ungetch(ch);
-	      return NUMBER;
-	    }
-	  }
+	  break;
+	}
+	if (!isdigit(ch)) {
+	  ungetch(ch);
+	  return NUMBER;
+	}
+      }
+      while (1) {
+	ch = getch();
+	if (ch == 'e' || ch == 'E')
+	  break;
+	if (!isdigit(ch)) {
+	  ungetch(ch);
+	  return NUMBER;
 	}
+      }
+      ch = getch();
+      if (ch == '-')
+	ch = getch();
+      if (!isdigit(ch)) {
+	yyerror("Badly formed number");
+	exit(1);
+      }
+      while (1) {
+	ch = getch();
 	if (!isdigit(ch)) {
 	  ungetch(ch);
 	  return NUMBER;
@@ -672,6 +704,8 @@
   else {
     ignore_line();
   }
+  line = 1;
+  column = 0;
 }
 
 int main(int argc, char *argv[]) 
@@ -680,7 +714,7 @@
   if (argc > 1 && strcmp("-", argv[1])) {
     filename = argv[1];
     if (freopen(filename, "r", stdin) == NULL) {
-      fprintf(stderr, "Error opening file %s\n", filename);
+      fprintf(stderr, "error opening file %s\n", filename);
       return 1;
     }
   }
@@ -690,6 +724,6 @@
 #endif
   rc = yyparse();
   if (rc) 
-    fprintf(stderr, "Error during parse\n");
+    fprintf(stderr, "error during parse\n");
   return rc;
 }