]> git.saurik.com Git - bison.git/blobdiff - src/parse-gram.y
* src/symtab.h, src/symtab.c (symbol_t): printer and
[bison.git] / src / parse-gram.y
index e5b07217751d8918e3ad923f478a9b6286ca573a..06a32c31da51c1ab14623b41e030c59d3b4c0b22 100644 (file)
 #include "files.h"
 #include "getargs.h"
 #include "output.h"
+#include "symlist.h"
 #include "gram.h"
 #include "reader.h"
 #include "conflicts.h"
 
+/* Produce verbose parse errors.  */
 #define YYERROR_VERBOSE 1
+#define YYLLOC_DEFAULT(Current, Rhs, N)                        \
+do {                                                   \
+  if (N)                                               \
+  {                                                    \
+    Current.first_column  = Rhs[1].first_column;       \
+    Current.first_line    = Rhs[1].first_line;         \
+    Current.last_column   = Rhs[N].last_column;                \
+    Current.last_line     = Rhs[N].last_line;          \
+  }                                                    \
+  else                                                 \
+  {                                                    \
+    Current = Rhs[0];                                  \
+  }                                                    \
+} while (0)
 
 /* Pass the control structure to YYPARSE and YYLEX. */
 #define YYPARSE_PARAM gram_control
    of the tokens.  */
 #define YYPRINT(File, Type, Value) \
         yyprint (File, &yylloc, Type, &Value)
-static void yyprint (FILE *file, const yyltype *loc,
+static void yyprint (FILE *file, const location_t *loc,
                      int type, const yystype *value);
 
 symbol_class current_class = unknown_sym;
 char *current_type = 0;
 symbol_t *current_lhs;
+location_t current_lhs_location;
 associativity current_assoc;
 int current_prec = 0;
+braced_code_t current_braced_code = action_braced_code;
 %}
 
 
@@ -72,6 +90,7 @@ int current_prec = 0;
 %union
 {
   symbol_t *symbol;
+  symbol_list_t *list;
   int integer;
   char *string;
   associativity assoc;
@@ -82,15 +101,21 @@ int current_prec = 0;
 %token STRING CHARACTER
 %token INT
 
-%token PERCENT_TOKEN "%token"
-%token PERCENT_NTERM "%nterm"
-%token PERCENT_TYPE "%type"
-%token PERCENT_UNION "%union"
+%token PERCENT_TOKEN       "%token"
+%token PERCENT_NTERM       "%nterm"
+
+%token PERCENT_TYPE        "%type"
+%token PERCENT_DESTRUCTOR  "%destructor"
+%token PERCENT_PRINTER     "%printer"
+
+%token PERCENT_UNION       "%union"
+
+%token PERCENT_LEFT        "%left"
+%token PERCENT_RIGHT       "%right"
+%token PERCENT_NONASSOC    "%nonassoc"
+
 %token PERCENT_EXPECT "%expect"
 %token PERCENT_START "%start"
-%token PERCENT_LEFT "%left"
-%token PERCENT_RIGHT "%right"
-%token PERCENT_NONASSOC "%nonassoc"
 %token PERCENT_PREC     "%prec"
 %token PERCENT_VERBOSE  "%verbose"
 %token PERCENT_ERROR_VERBOSE "%error-verbose"
@@ -122,31 +147,35 @@ int current_prec = 0;
 %token PROLOGUE EPILOGUE
 %token BRACED_CODE
 
-%type <string> CHARACTER TYPE  STRING string_content
+%type <string> CHARACTER TYPE STRING string_content
                BRACED_CODE PROLOGUE EPILOGUE epilogue.opt action
 %type <integer> INT
 %type <symbol> ID symbol string_as_id
-%type <assoc> precedence_directive
+%type <assoc> precedence_declarator
+%type <list>  symbols.1
 %%
-input: { LOCATION_RESET (yylloc); }
-  directives "%%" gram epilogue.opt
+
+input:
+  declarations "%%" grammar epilogue.opt
     {
       yycontrol->errcode = 0;
-      epilogue_set ($5, @5.first_line);
+      epilogue_set ($4, @4);
     }
 ;
 
-directives:
+
+       /*------------------------------------.
+       | Declarations: before the first %%.  |
+       `------------------------------------*/
+
+declarations:
   /* Nothing */
-| directives directive
+| declarations declaration semi_colon.opt
 ;
 
-directive:
-  grammar_directives
-| PROLOGUE
-   {
-     prologue_augment ($1, @1.first_line);
-   }
+declaration:
+  grammar_declaration
+| PROLOGUE                                 { prologue_augment ($1, @1); }
 | "%debug"                                 { debug_flag = 1; }
 | "%define" string_content string_content  { muscle_insert ($2, $3); }
 | "%defines"                               { defines_flag = 1; }
@@ -164,42 +193,77 @@ directive:
 | "%yacc"                                  { yacc_flag = 1; }
 ;
 
-grammar_directives:
-  precedence_directives
-| "%nterm" { current_class = nterm_sym; } symbol_defs.1
+grammar_declaration:
+  precedence_declaration
+| symbol_declaration
+| "%start" symbol
     {
-      current_class = unknown_sym;
-      current_type = NULL;
+      grammar_start_symbol_set ($2, @2);
     }
-| "%start" symbol
+| "%union" BRACED_CODE
     {
-      grammar_start_symbol_set ($2);
+      typed = 1;
+      MUSCLE_INSERT_INT ("stype_line", @2.first_line);
+      muscle_insert ("stype", $2);
     }
-| "%token" { current_class = token_sym; } symbol_defs.1
+| "%destructor"
+    { current_braced_code = destructor_braced_code; }
+  BRACED_CODE symbols.1
+    {
+      symbol_list_t *list;
+      for (list = $4; list; list = list->next)
+       symbol_destructor_set (list->sym, list->location, $3);
+      symbol_list_free ($4);
+      current_braced_code = action_braced_code;
+    }
+| "%printer"
+    { current_braced_code = printer_braced_code; }
+  BRACED_CODE symbols.1
+    {
+      symbol_list_t *list;
+      for (list = $4; list; list = list->next)
+       symbol_printer_set (list->sym, $3, list->location);
+      symbol_list_free ($4);
+      current_braced_code = action_braced_code;
+    }
+;
+
+symbol_declaration:
+  "%nterm" { current_class = nterm_sym; } symbol_defs.1
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
-| "%type" TYPE {current_type = $2; } nterms_to_type.1
+| "%token" { current_class = token_sym; } symbol_defs.1
     {
+      current_class = unknown_sym;
       current_type = NULL;
     }
-| "%union" BRACED_CODE semi_colon_opt
+| "%type" TYPE symbols.1
     {
-      typed = 1;
-      MUSCLE_INSERT_INT ("stype_line", @2.first_line);
-      muscle_insert ("stype", $2);
+      symbol_list_t *list;
+      for (list = $3; list; list = list->next)
+       symbol_type_set (list->sym, list->location, $2);
+      symbol_list_free ($3);
     }
 ;
 
-precedence_directives:
-  precedence_directive type.opt
-    { current_assoc = $1; ++current_prec; }
-  terms_to_prec.1
-    { current_assoc = non_assoc; current_type = NULL; }
+precedence_declaration:
+  precedence_declarator type.opt symbols.1
+    {
+      symbol_list_t *list;
+      ++current_prec;
+      for (list = $3; list; list = list->next)
+       {
+         symbol_type_set (list->sym, list->location, current_type);
+         symbol_precedence_set (list->sym, list->location, current_prec, $1);
+       }
+      symbol_list_free ($3);
+      current_type = NULL;
+    }
 ;
 
-precedence_directive:
+precedence_declarator:
   "%left"     { $$ = left_assoc; }
 | "%right"    { $$ = right_assoc; }
 | "%nonassoc" { $$ = non_assoc; }
@@ -211,26 +275,12 @@ type.opt:
 ;
 
 /* One or more nonterminals to be %typed. */
-nterms_to_type.1:
-  ID                   { symbol_type_set ($1, current_type); }
-| nterms_to_type.1 ID  { symbol_type_set ($2, current_type); }
-;
 
-/* One or more symbols to be given a precedence/associativity.  */
-terms_to_prec.1:
-  symbol
-    {
-      symbol_type_set ($1, current_type);
-      symbol_precedence_set ($1, current_prec, current_assoc);
-    }
-| terms_to_prec.1 symbol
-    {
-      symbol_type_set ($2, current_type);
-      symbol_precedence_set ($2, current_prec, current_assoc);
-    }
+symbols.1:
+  symbol            { $$ = symbol_list_new ($1, @1); }
+| symbols.1 symbol  { $$ = symbol_list_prepend ($1, $2, @2); }
 ;
 
-
 /* One token definition.  */
 symbol_def:
   TYPE
@@ -240,24 +290,24 @@ symbol_def:
 | ID
      {
        symbol_class_set ($1, current_class);
-       symbol_type_set ($1, current_type);
+       symbol_type_set ($1, @1, current_type);
      }
 | ID INT
     {
       symbol_class_set ($1, current_class);
-      symbol_type_set ($1, current_type);
+      symbol_type_set ($1, @1, current_type);
       symbol_user_token_number_set ($1, $2);
     }
 | ID string_as_id
     {
       symbol_class_set ($1, current_class);
-      symbol_type_set ($1, current_type);
+      symbol_type_set ($1, @1, current_type);
       symbol_make_alias ($1, $2);
     }
 | ID INT string_as_id
     {
       symbol_class_set ($1, current_class);
-      symbol_type_set ($1, current_type);
+      symbol_type_set ($1, @1, current_type);
       symbol_user_token_number_set ($1, $2);
       symbol_make_alias ($1, $3);
     }
@@ -271,28 +321,41 @@ symbol_defs.1:
     {;}
 ;
 
-gram:
+
+       /*------------------------------------------.
+       | The grammar section: between the two %%.  |
+       `------------------------------------------*/
+
+grammar:
+  rules_or_grammar_declaration
+| grammar rules_or_grammar_declaration
+;
+
+/* As a Bison extension, one can use the grammar declarations in the
+   body of the grammar.  But to remain LALR(1), they must be ended
+   with a semi-colon.  */
+rules_or_grammar_declaration:
   rules
-| gram rules
+| grammar_declaration ";"
 ;
 
 rules:
-  ID ":" { current_lhs = $1; } rhses.1 ";"
+  ID ":" { current_lhs = $1; current_lhs_location = @1; } rhses.1 ";"
     {;}
 ;
 
 rhses.1:
-  rhs                { grammar_rule_end (); }
-| rhses.1 "|" rhs    { grammar_rule_end (); }
+  rhs                { grammar_rule_end (@1); }
+| rhses.1 "|" rhs    { grammar_rule_end (@3); }
 ;
 
 rhs:
   /* Nothing.  */
-    { grammar_rule_begin (current_lhs); }
+    { grammar_rule_begin (current_lhs, current_lhs_location); }
 | rhs symbol
-    { grammar_current_rule_symbol_append ($2); }
+    { grammar_current_rule_symbol_append ($2, @2); }
 | rhs action
-    { grammar_current_rule_action_append ($2, @2.first_line); }
+    { grammar_current_rule_action_append ($2, @2); }
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3); }
 ;
@@ -300,7 +363,7 @@ rhs:
 symbol:
   ID              { $$ = $1; }
 | string_as_id    { $$ = $1; }
-| CHARACTER       { $$ = getsym ($1); }
+| CHARACTER       { $$ = getsym ($1, @1); }
 ;
 
 action:
@@ -312,7 +375,7 @@ action:
 string_as_id:
   STRING
     {
-      $$ = getsym ($1);
+      $$ = getsym ($1, @1);
       symbol_class_set ($$, token_sym);
     }
 ;
@@ -337,7 +400,7 @@ epilogue.opt:
     }
 ;
 
-semi_colon_opt:
+semi_colon.opt:
   /* Nothing.  */
 | ";"
 ;
@@ -348,7 +411,7 @@ semi_colon_opt:
 
 static void
 yyprint (FILE *file,
-         const yyltype *loc, int type, const yystype *value)
+         const location_t *loc, int type, const yystype *value)
 {
   fputs (" (", file);
   LOCATION_PRINT (file, *loc);
@@ -385,7 +448,7 @@ yyprint (FILE *file,
 
 void
 gram_error (gram_control_t *control ATTRIBUTE_UNUSED,
-           yyltype *yylloc, const char *msg)
+           location_t *yylloc, const char *msg)
 {
   LOCATION_PRINT (stderr, *yylloc);
   fprintf (stderr, ": %s\n", msg);