]> granicus.if.org Git - re2c/commitdiff
- Added support for \<!...\> to enable rule setup.
authorhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Tue, 12 Feb 2008 22:02:59 +0000 (22:02 +0000)
committerhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Tue, 12 Feb 2008 22:02:59 +0000 (22:02 +0000)
21 files changed:
re2c/CHANGELOG
re2c/bootstrap/parser.cc
re2c/bootstrap/scanner.cc
re2c/bootstrap/y.tab.h
re2c/code.cc
re2c/globals.h
re2c/htdocs/index.html
re2c/htdocs/manual.html
re2c/main.cc
re2c/parser.y
re2c/re.h
re2c/re2c.1.in
re2c/scanner.re
re2c/test/cond_error_09.c.c [new file with mode: 0755]
re2c/test/cond_error_09.c.re [new file with mode: 0755]
re2c/test/cond_error_10.c.c [new file with mode: 0755]
re2c/test/cond_error_10.c.re [new file with mode: 0755]
re2c/test/cond_error_11.c.c [new file with mode: 0755]
re2c/test/cond_error_11.c.re [new file with mode: 0755]
re2c/test/condition_15.csif.c [new file with mode: 0755]
re2c/test/condition_15.csif.re [new file with mode: 0755]

index a9bfea5095c6054d9f8692d3093e7d064c077082..8b78aee7d6ced10d4eabf676c576095537a05527 100644 (file)
@@ -1,5 +1,6 @@
 Version 0.13.2 (2007-??-??)
 ---------------------------
+- Added support for '<!...>' to enable rule setup.
 - Added support for '=>' style rules.
 - Added support for ':=' style rules.
 - Added support for ':=>' style rules.
index ec61cc73c7cc1ec5bca6003be33d8836a8baab8f..20abb6f82a749b832db8091fc50bb1e5adcd0ba0 100644 (file)
@@ -76,7 +76,8 @@
      STRING = 265,
      CONFIG = 266,
      VALUE = 267,
-     NUMBER = 268
+     NUMBER = 268,
+     SETUP = 269
    };
 #endif
 /* Tokens.  */
@@ -91,6 +92,7 @@
 #define CONFIG 266
 #define VALUE 267
 #define NUMBER 268
+#define SETUP 269
 
 
 
 #include <string.h>
 #include <stdlib.h>
 #include <iostream>
+#include <set>
 
 #include "globals.h"
 #include "parser.h"
@@ -130,6 +133,7 @@ static re2c::RegExpMap  specMap;
 static RegExp           *spec, *specNone = NULL;
 static RuleOpList       specStar;
 static Scanner          *in = NULL;
+static StringMap        ruleSetupMap;
 
 /* Bison version 1.875 emits a definition that is not working
  * with several g++ version. Hence we disable it here.
@@ -198,6 +202,25 @@ void context_rule(CondList *clist, RegExp *expr, RegExp *look, Str *newcond, Tok
        delete code;
 }
 
+void setup_rule(CondList *clist, Token *code)
+{
+       assert(clist);
+       assert(code);
+       context_check(clist);
+       if (bFirstPass) {
+               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               {
+                       if (ruleSetupMap.find(*it) != ruleSetupMap.end())
+                       {
+                               in->fatalf("code to setup rule '%s' is already defined", it->c_str());
+                       }
+                       ruleSetupMap[*it] = code->text.to_string();
+               }
+       }
+       delete clist;
+       delete code;
+}
+
 
 
 /* Enabling traces.  */
@@ -220,7 +243,7 @@ void context_rule(CondList *clist, RegExp *expr, RegExp *look, Str *newcond, Tok
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 106 "parser.y"
+#line 127 "parser.y"
 {
        re2c::Symbol    *symbol;
        re2c::RegExp    *regexp;
@@ -232,7 +255,7 @@ typedef union YYSTYPE
        re2c::CondList  *clist;
 }
 /* Line 187 of yacc.c.  */
-#line 236 "parser.cc"
+#line 259 "parser.cc"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -245,7 +268,7 @@ typedef union YYSTYPE
 
 
 /* Line 216 of yacc.c.  */
-#line 249 "parser.cc"
+#line 272 "parser.cc"
 
 #ifdef short
 # undef short
@@ -460,20 +483,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   89
+#define YYLAST   92
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  25
+#define YYNTOKENS  26
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  14
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  44
+#define YYNRULES  46
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  81
+#define YYNSTATES  88
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   268
+#define YYMAXUTOK   269
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -485,15 +508,15 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      23,    24,     2,     2,    20,     2,     2,    16,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    19,    15,
-      17,    14,    18,     2,     2,     2,     2,     2,     2,     2,
+      24,    25,     2,     2,    21,     2,     2,    17,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    20,    16,
+      18,    15,    19,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,    22,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,    23,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,    21,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    22,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -507,7 +530,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14
 };
 
 #if YYDEBUG
@@ -517,41 +540,42 @@ static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     4,     7,    10,    15,    20,    25,    30,
       34,    42,    50,    57,    64,    72,    80,    87,    94,    98,
-     102,   103,   105,   107,   111,   112,   116,   117,   120,   122,
-     126,   128,   132,   134,   137,   139,   142,   145,   147,   149,
-     152,   155,   157,   159,   161
+     102,   107,   112,   113,   115,   117,   121,   122,   126,   127,
+     130,   132,   136,   138,   142,   144,   147,   149,   152,   155,
+     157,   159,   162,   165,   167,   169,   171
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      26,     0,    -1,    -1,    26,    28,    -1,    26,    27,    -1,
-       7,    14,    33,    15,    -1,     7,    14,    33,    16,    -1,
-      11,    14,    12,    15,    -1,    11,    14,    13,    15,    -1,
-      33,    32,     8,    -1,    17,    29,    18,    33,    32,    31,
-       8,    -1,    17,    29,    18,    33,    32,    19,    31,    -1,
-      17,    29,    18,    32,    31,     8,    -1,    17,    29,    18,
-      32,    19,    31,    -1,    17,     5,    18,    33,    32,    31,
-       8,    -1,    17,     5,    18,    33,    32,    19,    31,    -1,
-      17,     5,    18,    32,    31,     8,    -1,    17,     5,    18,
-      32,    19,    31,    -1,     6,    31,     8,    -1,     6,    19,
-      31,    -1,    -1,    30,    -1,     7,    -1,    30,    20,     7,
-      -1,    -1,    14,    18,     7,    -1,    -1,    16,    33,    -1,
-      34,    -1,    33,    21,    34,    -1,    35,    -1,    34,    22,
-      35,    -1,    36,    -1,    35,    36,    -1,    38,    -1,    38,
-      37,    -1,    38,     3,    -1,     4,    -1,     5,    -1,    37,
-       4,    -1,    37,     5,    -1,     7,    -1,     9,    -1,    10,
-      -1,    23,    33,    24,    -1
+      27,     0,    -1,    -1,    27,    29,    -1,    27,    28,    -1,
+       7,    15,    34,    16,    -1,     7,    15,    34,    17,    -1,
+      11,    15,    12,    16,    -1,    11,    15,    13,    16,    -1,
+      34,    33,     8,    -1,    18,    30,    19,    34,    33,    32,
+       8,    -1,    18,    30,    19,    34,    33,    20,    32,    -1,
+      18,    30,    19,    33,    32,     8,    -1,    18,    30,    19,
+      33,    20,    32,    -1,    18,     5,    19,    34,    33,    32,
+       8,    -1,    18,     5,    19,    34,    33,    20,    32,    -1,
+      18,     5,    19,    33,    32,     8,    -1,    18,     5,    19,
+      33,    20,    32,    -1,     6,    32,     8,    -1,     6,    20,
+      32,    -1,    14,     5,    19,     8,    -1,    14,    30,    19,
+       8,    -1,    -1,    31,    -1,     7,    -1,    31,    21,     7,
+      -1,    -1,    15,    19,     7,    -1,    -1,    17,    34,    -1,
+      35,    -1,    34,    22,    35,    -1,    36,    -1,    35,    23,
+      36,    -1,    37,    -1,    36,    37,    -1,    39,    -1,    39,
+      38,    -1,    39,     3,    -1,     4,    -1,     5,    -1,    38,
+       4,    -1,    38,     5,    -1,     7,    -1,     9,    -1,    10,
+      -1,    24,    34,    25,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   135,   135,   139,   140,   144,   152,   156,   162,   170,
-     179,   183,   188,   193,   199,   207,   215,   220,   226,   238,
-     254,   257,   264,   269,   278,   281,   289,   292,   299,   303,
-     310,   314,   325,   329,   336,   340,   355,   362,   366,   370,
-     374,   381,   389,   393,   397
+       0,   156,   156,   160,   161,   165,   173,   177,   183,   191,
+     200,   204,   209,   214,   220,   228,   236,   241,   247,   259,
+     271,   277,   285,   288,   295,   300,   309,   312,   320,   323,
+     330,   334,   341,   345,   356,   360,   367,   371,   386,   393,
+     397,   401,   405,   412,   420,   424,   428
 };
 #endif
 
@@ -561,10 +585,10 @@ static const yytype_uint16 yyrline[] =
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "CLOSESIZE", "CLOSE", "STAR", "NOCOND",
-  "ID", "CODE", "RANGE", "STRING", "CONFIG", "VALUE", "NUMBER", "'='",
-  "';'", "'/'", "'<'", "'>'", "':'", "','", "'|'", "'\\\\'", "'('", "')'",
-  "$accept", "spec", "decl", "rule", "cond", "clist", "newcond", "look",
-  "expr", "diff", "term", "factor", "close", "primary", 0
+  "ID", "CODE", "RANGE", "STRING", "CONFIG", "VALUE", "NUMBER", "SETUP",
+  "'='", "';'", "'/'", "'<'", "'>'", "':'", "','", "'|'", "'\\\\'", "'('",
+  "')'", "$accept", "spec", "decl", "rule", "cond", "clist", "newcond",
+  "look", "expr", "diff", "term", "factor", "close", "primary", 0
 };
 #endif
 
@@ -574,19 +598,19 @@ static const char *const yytname[] =
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,    61,    59,    47,    60,    62,    58,
-      44,   124,    92,    40,    41
+     265,   266,   267,   268,   269,    61,    59,    47,    60,    62,
+      58,    44,   124,    92,    40,    41
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    25,    26,    26,    26,    27,    27,    27,    27,    28,
-      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
+       0,    26,    27,    27,    27,    28,    28,    28,    28,    29,
+      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
       29,    29,    30,    30,    31,    31,    32,    32,    33,    33,
-      34,    34,    35,    35,    36,    36,    36,    37,    37,    37,
-      37,    38,    38,    38,    38
+      34,    34,    35,    35,    36,    36,    37,    37,    37,    38,
+      38,    38,    38,    39,    39,    39,    39
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -594,9 +618,9 @@ static const yytype_uint8 yyr2[] =
 {
        0,     2,     0,     2,     2,     4,     4,     4,     4,     3,
        7,     7,     6,     6,     7,     7,     6,     6,     3,     3,
-       0,     1,     1,     3,     0,     3,     0,     2,     1,     3,
-       1,     3,     1,     2,     1,     2,     2,     1,     1,     2,
-       2,     1,     1,     1,     3
+       4,     4,     0,     1,     1,     3,     0,     3,     0,     2,
+       1,     3,     1,     3,     1,     2,     1,     2,     2,     1,
+       1,     2,     2,     1,     1,     1,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -604,45 +628,45 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     0,     1,    24,    41,    42,    43,     0,    20,     0,
-       4,     3,    26,    28,    30,    32,    34,     0,    24,     0,
-       0,     0,     0,    22,     0,    21,    41,     0,     0,     0,
-       0,     0,    33,    36,    37,    38,    35,     0,    19,    18,
-       0,     0,     0,    26,    26,     0,    44,    27,    29,     9,
-      31,    39,    40,    25,     5,     6,     7,     8,    24,    26,
-      24,    26,    23,    24,     0,    24,    24,     0,    24,    17,
-      16,    24,     0,    13,    12,    24,     0,    15,    14,    11,
-      10
+       2,     0,     1,    26,    43,    44,    45,     0,    22,    22,
+       0,     4,     3,    28,    30,    32,    34,    36,     0,    26,
+       0,     0,     0,     0,    24,     0,    23,     0,     0,    43,
+       0,     0,     0,     0,     0,    35,    38,    39,    40,    37,
+       0,    19,    18,     0,     0,     0,     0,     0,     0,    28,
+      28,    46,    29,    31,     9,    33,    41,    42,    27,     5,
+       6,     7,     8,    20,    21,    25,    26,    28,    26,    28,
+      26,     0,    26,    26,     0,    26,    17,    16,    26,     0,
+      13,    12,    26,     0,    15,    14,    11,    10
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     1,    10,    11,    24,    25,    19,    30,    12,    13,
-      14,    15,    36,    16
+      -1,     1,    11,    12,    25,    26,    20,    33,    13,    14,
+      15,    16,    39,    17
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -38
+#define YYPACT_NINF -42
 static const yytype_int8 yypact[] =
 {
-     -38,     2,   -38,    -9,   -11,   -38,   -38,    29,    51,     7,
-     -38,   -38,    10,    33,     7,   -38,    57,    34,    49,    60,
-       7,    52,    53,   -38,    54,    50,   -38,     8,     7,     7,
-      61,     7,   -38,   -38,   -38,   -38,    62,    66,   -38,   -38,
-      20,    59,    63,    11,    11,    68,   -38,    55,    33,   -38,
-       7,   -38,   -38,   -38,   -38,   -38,   -38,   -38,    14,    10,
-      30,    10,   -38,    49,    69,    32,    49,    71,    40,   -38,
-     -38,    49,    72,   -38,   -38,    49,    73,   -38,   -38,   -38,
-     -38
+     -42,     7,   -42,    -5,   -11,   -42,   -42,     8,    59,    60,
+      -4,   -42,   -42,     2,   -12,    -4,   -42,    57,    27,    55,
+      63,    -4,    23,    53,   -42,    54,    56,    61,    62,   -42,
+      33,    -4,    -4,    66,    -4,   -42,   -42,   -42,   -42,    64,
+      68,   -42,   -42,    16,    67,    69,    70,    71,    75,    20,
+      20,   -42,    65,   -12,   -42,    -4,   -42,   -42,   -42,   -42,
+     -42,   -42,   -42,   -42,   -42,   -42,    19,     2,    28,     2,
+      55,    76,    30,    55,    78,    37,   -42,   -42,    55,    80,
+     -42,   -42,    55,    81,   -42,   -42,   -42,   -42
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -38,   -38,   -38,   -38,   -38,   -38,   -18,   -37,    -5,    56,
-      58,   -13,   -38,   -38
+     -42,   -42,   -42,   -42,    82,   -42,   -19,   -41,    -9,    44,
+      58,   -13,   -42,   -42
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -652,43 +676,45 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      38,    32,     2,    20,    27,    17,    58,    60,     3,     4,
-      18,     5,     6,     7,    26,    40,     5,     6,    26,     8,
-       5,     6,    65,    47,    68,     9,    28,    28,    17,    29,
-       9,    29,    46,    63,     9,    54,    55,    32,    59,    61,
-      64,    29,    67,    21,    17,    69,    17,    72,    73,    66,
-      76,    71,    37,    77,    17,    31,    22,    79,    23,    75,
-      33,    34,    35,    17,    41,    42,    51,    52,    39,    49,
-      45,    43,    44,    53,    56,    62,    29,    70,    57,    74,
-      78,    80,     0,     0,     0,    48,     0,     0,     0,    50
+      41,    30,    35,    29,    21,     5,     6,     2,    66,    68,
+      18,    34,    43,     3,     4,    19,     5,     6,     7,    31,
+      10,     8,    52,    22,    32,     9,    72,    29,    75,     5,
+       6,    10,    59,    60,    18,    44,    45,    31,    32,    70,
+      67,    69,    35,    18,    10,    18,    40,    71,    73,    74,
+      78,    76,    18,    79,    80,    32,    83,    82,    51,    84,
+      36,    37,    38,    86,    23,    27,    24,    24,    56,    57,
+      18,    42,    46,    47,    54,    58,    53,    48,    63,    64,
+      49,    50,    65,    61,    77,    62,    81,    32,    85,    87,
+       0,    28,    55
 };
 
 static const yytype_int8 yycheck[] =
 {
-      18,    14,     0,    14,     9,    14,    43,    44,     6,     7,
-      19,     9,    10,    11,     7,    20,     9,    10,     7,    17,
-       9,    10,    59,    28,    61,    23,    16,    16,    14,    21,
-      23,    21,    24,    19,    23,    15,    16,    50,    43,    44,
-      58,    21,    60,    14,    14,    63,    14,    65,    66,    19,
-      68,    19,    18,    71,    14,    22,     5,    75,     7,    19,
-       3,     4,     5,    14,    12,    13,     4,     5,     8,     8,
-      20,    18,    18,     7,    15,     7,    21,     8,    15,     8,
-       8,     8,    -1,    -1,    -1,    29,    -1,    -1,    -1,    31
+      19,    10,    15,     7,    15,     9,    10,     0,    49,    50,
+      15,    23,    21,     6,     7,    20,     9,    10,    11,    17,
+      24,    14,    31,    15,    22,    18,    67,     7,    69,     9,
+      10,    24,    16,    17,    15,    12,    13,    17,    22,    20,
+      49,    50,    55,    15,    24,    15,    19,    66,    20,    68,
+      20,    70,    15,    72,    73,    22,    75,    20,    25,    78,
+       3,     4,     5,    82,     5,     5,     7,     7,     4,     5,
+      15,     8,    19,    19,     8,     7,    32,    21,     8,     8,
+      19,    19,     7,    16,     8,    16,     8,    22,     8,     8,
+      -1,     9,    34
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    26,     0,     6,     7,     9,    10,    11,    17,    23,
-      27,    28,    33,    34,    35,    36,    38,    14,    19,    31,
-      14,    14,     5,     7,    29,    30,     7,    33,    16,    21,
-      32,    22,    36,     3,     4,     5,    37,    18,    31,     8,
-      33,    12,    13,    18,    18,    20,    24,    33,    34,     8,
-      35,     4,     5,     7,    15,    16,    15,    15,    32,    33,
-      32,    33,     7,    19,    31,    32,    19,    31,    32,    31,
-       8,    19,    31,    31,     8,    19,    31,    31,     8,    31,
-       8
+       0,    27,     0,     6,     7,     9,    10,    11,    14,    18,
+      24,    28,    29,    34,    35,    36,    37,    39,    15,    20,
+      32,    15,    15,     5,     7,    30,    31,     5,    30,     7,
+      34,    17,    22,    33,    23,    37,     3,     4,     5,    38,
+      19,    32,     8,    34,    12,    13,    19,    19,    21,    19,
+      19,    25,    34,    35,     8,    36,     4,     5,     7,    16,
+      17,    16,    16,     8,     8,     7,    33,    34,    33,    34,
+      20,    32,    33,    20,    32,    33,    32,     8,    20,    32,
+      32,     8,    20,    32,    32,     8,    32,     8
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1503,7 +1529,7 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 135 "parser.y"
+#line 156 "parser.y"
     {
                        accept = 0;
                        spec = NULL;
@@ -1511,7 +1537,7 @@ yyreduce:
     break;
 
   case 5:
-#line 145 "parser.y"
+#line 166 "parser.y"
     {
                        if((yyvsp[(1) - (4)].symbol)->re)
                        {
@@ -1522,14 +1548,14 @@ yyreduce:
     break;
 
   case 6:
-#line 153 "parser.y"
+#line 174 "parser.y"
     {
                        in->fatal("trailing contexts are not allowed in named definitions");
                }
     break;
 
   case 7:
-#line 157 "parser.y"
+#line 178 "parser.y"
     {
                        in->config(*(yyvsp[(1) - (4)].str), *(yyvsp[(3) - (4)].str));
                        delete (yyvsp[(1) - (4)].str);
@@ -1538,7 +1564,7 @@ yyreduce:
     break;
 
   case 8:
-#line 163 "parser.y"
+#line 184 "parser.y"
     {
                        in->config(*(yyvsp[(1) - (4)].str), (yyvsp[(3) - (4)].number));
                        delete (yyvsp[(1) - (4)].str);
@@ -1546,7 +1572,7 @@ yyreduce:
     break;
 
   case 9:
-#line 171 "parser.y"
+#line 192 "parser.y"
     {
                        if (cFlag)
                        {
@@ -1558,14 +1584,14 @@ yyreduce:
     break;
 
   case 10:
-#line 180 "parser.y"
+#line 201 "parser.y"
     {
                        context_rule((yyvsp[(2) - (7)].clist), (yyvsp[(4) - (7)].regexp), (yyvsp[(5) - (7)].regexp), (yyvsp[(6) - (7)].str), (yyvsp[(7) - (7)].token));
                }
     break;
 
   case 11:
-#line 184 "parser.y"
+#line 205 "parser.y"
     {
                        assert((yyvsp[(7) - (7)].str));
                        context_rule((yyvsp[(2) - (7)].clist), (yyvsp[(4) - (7)].regexp), (yyvsp[(5) - (7)].regexp), (yyvsp[(7) - (7)].str), NULL);
@@ -1573,7 +1599,7 @@ yyreduce:
     break;
 
   case 12:
-#line 189 "parser.y"
+#line 210 "parser.y"
     {
                        context_none((yyvsp[(2) - (6)].clist));
                        delete (yyvsp[(5) - (6)].str);
@@ -1581,7 +1607,7 @@ yyreduce:
     break;
 
   case 13:
-#line 194 "parser.y"
+#line 215 "parser.y"
     {
                        assert((yyvsp[(6) - (6)].str));
                        context_none((yyvsp[(2) - (6)].clist));
@@ -1590,7 +1616,7 @@ yyreduce:
     break;
 
   case 14:
-#line 200 "parser.y"
+#line 221 "parser.y"
     {
                        context_check(NULL);
                        Token *token = new Token((yyvsp[(7) - (7)].token), (yyvsp[(7) - (7)].token)->line, (yyvsp[(6) - (7)].str));
@@ -1601,7 +1627,7 @@ yyreduce:
     break;
 
   case 15:
-#line 208 "parser.y"
+#line 229 "parser.y"
     {
                        assert((yyvsp[(7) - (7)].str));
                        context_check(NULL);
@@ -1612,7 +1638,7 @@ yyreduce:
     break;
 
   case 16:
-#line 216 "parser.y"
+#line 237 "parser.y"
     {
                        context_none(NULL);
                        delete (yyvsp[(5) - (6)].str);
@@ -1620,7 +1646,7 @@ yyreduce:
     break;
 
   case 17:
-#line 221 "parser.y"
+#line 242 "parser.y"
     {
                        assert((yyvsp[(6) - (6)].str));
                        context_none(NULL);
@@ -1629,7 +1655,7 @@ yyreduce:
     break;
 
   case 18:
-#line 227 "parser.y"
+#line 248 "parser.y"
     {
                        context_check(NULL);
                        if (specNone)
@@ -1644,7 +1670,7 @@ yyreduce:
     break;
 
   case 19:
-#line 239 "parser.y"
+#line 260 "parser.y"
     {
                        assert((yyvsp[(3) - (3)].str));
                        context_check(NULL);
@@ -1659,86 +1685,102 @@ yyreduce:
     break;
 
   case 20:
-#line 254 "parser.y"
+#line 272 "parser.y"
     {
-                       in->fatal("unnamed condition not supported");
+                       CondList *clist = new CondList();
+                       clist->insert("*");
+                       setup_rule(clist, (yyvsp[(4) - (4)].token));
                }
     break;
 
   case 21:
-#line 258 "parser.y"
+#line 278 "parser.y"
     {
-                       (yyval.clist) = (yyvsp[(1) - (1)].clist);
+                       setup_rule((yyvsp[(2) - (4)].clist), (yyvsp[(4) - (4)].token));
                }
     break;
 
   case 22:
-#line 265 "parser.y"
+#line 285 "parser.y"
+    {
+                       in->fatal("unnamed condition not supported");
+               }
+    break;
+
+  case 23:
+#line 289 "parser.y"
+    {
+                       (yyval.clist) = (yyvsp[(1) - (1)].clist);
+               }
+    break;
+
+  case 24:
+#line 296 "parser.y"
     {
                        (yyval.clist) = new CondList();
                        (yyval.clist)->insert((yyvsp[(1) - (1)].symbol)->GetName().to_string());
                }
     break;
 
-  case 23:
-#line 270 "parser.y"
+  case 25:
+#line 301 "parser.y"
     {
                        (yyvsp[(1) - (3)].clist)->insert((yyvsp[(3) - (3)].symbol)->GetName().to_string());
                        (yyval.clist) = (yyvsp[(1) - (3)].clist);
                }
     break;
 
-  case 24:
-#line 278 "parser.y"
+  case 26:
+#line 309 "parser.y"
     {
                        (yyval.str) = NULL;
                }
     break;
 
-  case 25:
-#line 282 "parser.y"
+  case 27:
+#line 313 "parser.y"
     {
                        (yyval.str) = new Str((yyvsp[(3) - (3)].symbol)->GetName().to_string().c_str());
                }
     break;
 
-  case 26:
-#line 289 "parser.y"
+  case 28:
+#line 320 "parser.y"
     {
                        (yyval.regexp) = new NullOp;
                }
     break;
 
-  case 27:
-#line 293 "parser.y"
+  case 29:
+#line 324 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(2) - (2)].regexp);
                }
     break;
 
-  case 28:
-#line 300 "parser.y"
+  case 30:
+#line 331 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 29:
-#line 304 "parser.y"
+  case 31:
+#line 335 "parser.y"
     {
                        (yyval.regexp) = mkAlt((yyvsp[(1) - (3)].regexp), (yyvsp[(3) - (3)].regexp));
                }
     break;
 
-  case 30:
-#line 311 "parser.y"
+  case 32:
+#line 342 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 31:
-#line 315 "parser.y"
+  case 33:
+#line 346 "parser.y"
     {
                        (yyval.regexp) = mkDiff((yyvsp[(1) - (3)].regexp), (yyvsp[(3) - (3)].regexp));
                        if(!(yyval.regexp))
@@ -1748,29 +1790,29 @@ yyreduce:
                }
     break;
 
-  case 32:
-#line 326 "parser.y"
+  case 34:
+#line 357 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 33:
-#line 330 "parser.y"
+  case 35:
+#line 361 "parser.y"
     {
                        (yyval.regexp) = new CatOp((yyvsp[(1) - (2)].regexp), (yyvsp[(2) - (2)].regexp));
                }
     break;
 
-  case 34:
-#line 337 "parser.y"
+  case 36:
+#line 368 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 35:
-#line 341 "parser.y"
+  case 37:
+#line 372 "parser.y"
     {
                        switch((yyvsp[(2) - (2)].op))
                        {
@@ -1787,43 +1829,43 @@ yyreduce:
                }
     break;
 
-  case 36:
-#line 356 "parser.y"
+  case 38:
+#line 387 "parser.y"
     {
                        (yyval.regexp) = new CloseVOp((yyvsp[(1) - (2)].regexp), (yyvsp[(2) - (2)].extop).minsize, (yyvsp[(2) - (2)].extop).maxsize);
                }
     break;
 
-  case 37:
-#line 363 "parser.y"
+  case 39:
+#line 394 "parser.y"
     {
                        (yyval.op) = (yyvsp[(1) - (1)].op);
                }
     break;
 
-  case 38:
-#line 367 "parser.y"
+  case 40:
+#line 398 "parser.y"
     {
                        (yyval.op) = (yyvsp[(1) - (1)].op);
                }
     break;
 
-  case 39:
-#line 371 "parser.y"
+  case 41:
+#line 402 "parser.y"
     {
                        (yyval.op) = ((yyvsp[(1) - (2)].op) == (yyvsp[(2) - (2)].op)) ? (yyvsp[(1) - (2)].op) : '*';
                }
     break;
 
-  case 40:
-#line 375 "parser.y"
+  case 42:
+#line 406 "parser.y"
     {
                        (yyval.op) = ((yyvsp[(1) - (2)].op) == (yyvsp[(2) - (2)].op)) ? (yyvsp[(1) - (2)].op) : '*';
                }
     break;
 
-  case 41:
-#line 382 "parser.y"
+  case 43:
+#line 413 "parser.y"
     {
                        if(!(yyvsp[(1) - (1)].symbol)->re)
                        {
@@ -1833,22 +1875,22 @@ yyreduce:
                }
     break;
 
-  case 42:
-#line 390 "parser.y"
+  case 44:
+#line 421 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 43:
-#line 394 "parser.y"
+  case 45:
+#line 425 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(1) - (1)].regexp);
                }
     break;
 
-  case 44:
-#line 398 "parser.y"
+  case 46:
+#line 429 "parser.y"
     {
                        (yyval.regexp) = (yyvsp[(2) - (3)].regexp);
                }
@@ -1856,7 +1898,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 1860 "parser.cc"
+#line 1902 "parser.cc"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2070,7 +2112,7 @@ yyreturn:
 }
 
 
-#line 403 "parser.y"
+#line 434 "parser.y"
 
 
 extern "C" {
@@ -2101,20 +2143,21 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
        o << " */\n";
        o << sourceFileInfo;
        
-       while(i.echo())
+       while (i.echo())
        {
                bool bPrologBrace = false;
                yyparse();
                if (cFlag)
                {
                        RegExpMap::iterator it;
+                       StringMap::const_iterator itRuleSetup;
 
                        if (!specStar.empty())
                        {
-                               for(it = specMap.begin(); it != specMap.end(); ++it)
+                               for (it = specMap.begin(); it != specMap.end(); ++it)
                                {
                                        assert(it->second.second);
-                                       for(RuleOpList::const_iterator itOp = specStar.begin(); itOp != specStar.end(); ++itOp)
+                                       for (RuleOpList::const_iterator itOp = specStar.begin(); itOp != specStar.end(); ++itOp)
                                        {
                                                it->second.second = mkAlt((*itOp)->copy(accept++), it->second.second);
                                        }
@@ -2132,16 +2175,46 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                        {
                                // We reserved 0 for specNone but it is not present,
                                // so we can decrease all specs.
-                               for(it = specMap.begin(); it != specMap.end(); ++it)
+                               for (it = specMap.begin(); it != specMap.end(); ++it)
                                {
                                        it->second.first--;
                                }
                        }
 
                        size_t nCount = specMap.size();
-                       for(it = specMap.begin(); it != specMap.end(); ++it)
+
+                       for (itRuleSetup = ruleSetupMap.begin(); itRuleSetup != ruleSetupMap.end(); ++itRuleSetup)
+                       {
+                               if (itRuleSetup->first != "*" && specMap.find(itRuleSetup->first) == specMap.end())
+                               {
+                                       in->fatalf("Setup for non existing rule '%s' found", itRuleSetup->first.c_str());
+                               }
+                       }
+                       if (nCount < (ruleSetupMap.find("*") == ruleSetupMap.end() ? ruleSetupMap.size() : ruleSetupMap.size()))
+                       {
+                               in->fatalf("Setup for all rules with '*' not possible when all rules are setup explicitly");
+                       }
+                       for (it = specMap.begin(); it != specMap.end(); ++it)
                        {
                                assert(it->second.second);
+
+                               itRuleSetup = ruleSetupMap.find(it->first);                             
+                               if (itRuleSetup != ruleSetupMap.end())
+                               {
+                                       yySetupRule = itRuleSetup->second;
+                               }
+                               else
+                               {
+                                       itRuleSetup = ruleSetupMap.find("*");
+                                       if (itRuleSetup != ruleSetupMap.end())
+                                       {
+                                               yySetupRule = itRuleSetup->second;
+                                       }
+                                       else
+                                       {
+                                               yySetupRule = "";
+                                       }
+                               }
                                genCode(o, topIndent, it->second.second, &specMap, it->first, !--nCount, bPrologBrace);
                        }
                        if (h)
@@ -2153,7 +2226,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                genTypes(typesInline, 0, specMap);
                        }
                }
-               else if(spec)
+               else if (spec)
                {
                        genCode(o, topIndent, spec, NULL, "", 0, bPrologBrace);
                }
index 4a1bcfcc07c45643ac4f04d933e023ffd4dd80cd..38beb3cc9cbf184811c655221e2cf838a208500d 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.2.dev on Tue Jan 22 17:06:50 2008 */
+/* Generated by re2c 0.13.2.dev on Tue Feb 12 22:20:54 2008 */
 /* $Id$ */
 #include <stdlib.h>
 #include <string.h>
@@ -206,7 +206,7 @@ yy16:
        yych = *++YYCURSOR;
        if (yych != '!') goto yy13;
        yych = *++YYCURSOR;
-       switch(yych) {
+       switch (yych) {
        case 'g':       goto yy20;
        case 'i':       goto yy19;
        case 'm':       goto yy21;
@@ -500,10 +500,10 @@ yy71:
        yyaccept = 0;
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych <= '/') {
-               if (yych == ',') goto yy154;
+               if (yych == ',') goto yy156;
        } else {
-               if (yych <= '0') goto yy151;
-               if (yych <= '9') goto yy152;
+               if (yych <= '0') goto yy153;
+               if (yych <= '9') goto yy154;
        }
 yy72:
        {
@@ -513,7 +513,7 @@ yy72:
 yy73:
        YYCTXMARKER = YYCURSOR + 1;
        ++YYCURSOR;
-       if ((yych = *YYCURSOR) == '=') goto yy147;
+       if ((yych = *YYCURSOR) == '=') goto yy149;
 yy74:
        {
                                        std::ostringstream msg;
@@ -524,14 +524,14 @@ yy74:
                                }
 yy75:
        ++YYCURSOR;
-       if ((yych = *YYCURSOR) == '*') goto yy145;
+       if ((yych = *YYCURSOR) == '*') goto yy147;
 yy76:
        {
                                        RETURN(*tok);
                                }
 yy77:
        ++YYCURSOR;
-       if ((yych = *YYCURSOR) == '/') goto yy143;
+       if ((yych = *YYCURSOR) == '/') goto yy145;
        {
                                        yylval.op = *tok;
                                        RETURN(STAR);
@@ -539,7 +539,7 @@ yy77:
 yy79:
        yyaccept = 1;
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych != 0x0A) goto yy139;
+       if (yych != 0x0A) goto yy141;
 yy80:
        {
                                        fatal("unterminated string constant (missing \")");
@@ -547,7 +547,7 @@ yy80:
 yy81:
        yyaccept = 2;
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych != 0x0A) goto yy134;
+       if (yych != 0x0A) goto yy136;
 yy82:
        {
                                        fatal("unterminated string constant (missing ')");
@@ -556,8 +556,8 @@ yy83:
        yyaccept = 3;
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == 0x0A) goto yy84;
-       if (yych == '^') goto yy125;
-       goto yy124;
+       if (yych == '^') goto yy127;
+       goto yy126;
 yy84:
        {
                                        fatal("unterminated range (missing ])");
@@ -565,7 +565,8 @@ yy84:
 yy85:
        yyaccept = 4;
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == '>') goto yy116;
+       if (yych == '!') goto yy116;
+       if (yych == '>') goto yy118;
        goto yy76;
 yy86:
        yych = *++YYCURSOR;
@@ -687,7 +688,7 @@ yy109:
                        if (yyaccept <= 6) {
                                goto yy112;
                        } else {
-                               goto yy155;
+                               goto yy157;
                        }
                }
        }
@@ -749,204 +750,209 @@ yy114:
                }
        }
 yy116:
+       ++YYCURSOR;
+       {
+                                       RETURN(SETUP);
+                               }
+yy118:
        YYCTXMARKER = YYCURSOR + 1;
        yych = *++YYCURSOR;
-       goto yy118;
-yy117:
+       goto yy120;
+yy119:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
-yy118:
+yy120:
        if (yybm[0+yych] & 8) {
-               goto yy117;
+               goto yy119;
        }
        if (yych <= '<') {
-               if (yych == ':') goto yy122;
+               if (yych == ':') goto yy124;
                goto yy109;
        } else {
-               if (yych <= '=') goto yy121;
+               if (yych <= '=') goto yy123;
                if (yych != '{') goto yy109;
        }
-yy119:
+yy121:
        ++YYCURSOR;
        YYCURSOR = YYCTXMARKER;
        {
                                        RETURN(NOCOND);
                                }
-yy121:
+yy123:
        yych = *++YYCURSOR;
-       if (yych == '>') goto yy119;
+       if (yych == '>') goto yy121;
        goto yy109;
-yy122:
+yy124:
        yych = *++YYCURSOR;
-       if (yych == '=') goto yy119;
+       if (yych == '=') goto yy121;
        goto yy109;
-yy123:
+yy125:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy124:
+yy126:
        if (yybm[0+yych] & 16) {
-               goto yy123;
+               goto yy125;
        }
        if (yych <= '[') goto yy109;
-       if (yych <= '\\') goto yy127;
-       goto yy128;
-yy125:
+       if (yych <= '\\') goto yy129;
+       goto yy130;
+yy127:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych <= '[') {
                if (yych == 0x0A) goto yy109;
-               goto yy125;
+               goto yy127;
        } else {
-               if (yych <= '\\') goto yy130;
-               if (yych <= ']') goto yy131;
-               goto yy125;
+               if (yych <= '\\') goto yy132;
+               if (yych <= ']') goto yy133;
+               goto yy127;
        }
-yy127:
+yy129:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych == 0x0A) goto yy109;
-       goto yy123;
-yy128:
+       goto yy125;
+yy130:
        ++YYCURSOR;
        {
                                        cur = cursor;
                                        yylval.regexp = ranToRE(token());
                                        return RANGE;
                                }
-yy130:
+yy132:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych == 0x0A) goto yy109;
-       goto yy125;
-yy131:
+       goto yy127;
+yy133:
        ++YYCURSOR;
        {
                                        cur = cursor;
                                        yylval.regexp = invToRE(token());
                                        return RANGE;
                                }
-yy133:
+yy135:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy134:
+yy136:
        if (yybm[0+yych] & 32) {
-               goto yy133;
+               goto yy135;
        }
        if (yych <= '&') goto yy109;
-       if (yych <= '\'') goto yy136;
+       if (yych <= '\'') goto yy138;
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych == 0x0A) goto yy109;
-       goto yy133;
-yy136:
+       goto yy135;
+yy138:
        ++YYCURSOR;
        {
                                        cur = cursor;
                                        yylval.regexp = strToCaseInsensitiveRE(token());
                                        return STRING;
                                }
-yy138:
+yy140:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy139:
+yy141:
        if (yybm[0+yych] & 64) {
-               goto yy138;
+               goto yy140;
        }
        if (yych <= '!') goto yy109;
-       if (yych <= '"') goto yy141;
+       if (yych <= '"') goto yy143;
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych == 0x0A) goto yy109;
-       goto yy138;
-yy141:
+       goto yy140;
+yy143:
        ++YYCURSOR;
        {
                                        cur = cursor;
                                        yylval.regexp = strToRE(token());
                                        return STRING;
                                }
-yy143:
+yy145:
        ++YYCURSOR;
        {
                                        tok = cursor;
                                        RETURN(0);
                                }
-yy145:
+yy147:
        ++YYCURSOR;
        {
                                        depth = 1;
                                        goto comment;
                                }
-yy147:
+yy149:
        ++YYCURSOR;
-       if ((yych = *YYCURSOR) == '>') goto yy149;
+       if ((yych = *YYCURSOR) == '>') goto yy151;
        {
                                        cur = cursor;
                                        tok+= 2; /* skip ":=" */
                                        depth = 0;
                                        goto code;
                                }
-yy149:
+yy151:
        ++YYCURSOR;
        YYCURSOR = YYCTXMARKER;
        {
                                        RETURN(*tok);
                                }
-yy151:
+yy153:
        yych = *++YYCURSOR;
-       if (yych == ',') goto yy165;
-       goto yy153;
-yy152:
+       if (yych == ',') goto yy167;
+       goto yy155;
+yy154:
        ++YYCURSOR;
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
-yy153:
+yy155:
        if (yybm[0+yych] & 128) {
-               goto yy152;
+               goto yy154;
        }
-       if (yych == ',') goto yy158;
-       if (yych == '}') goto yy156;
+       if (yych == ',') goto yy160;
+       if (yych == '}') goto yy158;
        goto yy109;
-yy154:
+yy156:
        ++YYCURSOR;
-yy155:
+yy157:
        {
                                        fatal("illegal closure form, use '{n}', '{n,}', '{n,m}' where n and m are numbers");
                                }
-yy156:
+yy158:
        ++YYCURSOR;
        {
                                        yylval.extop.minsize = atoi((char *)tok+1);
                                        yylval.extop.maxsize = atoi((char *)tok+1);
                                        RETURN(CLOSESIZE);
                                }
-yy158:
+yy160:
        yyaccept = 7;
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych <= '/') goto yy155;
-       if (yych <= '9') goto yy161;
-       if (yych != '}') goto yy155;
+       if (yych <= '/') goto yy157;
+       if (yych <= '9') goto yy163;
+       if (yych != '}') goto yy157;
        ++YYCURSOR;
        {
                                        yylval.extop.minsize = atoi((char *)tok+1);
                                        yylval.extop.maxsize = -1;
                                        RETURN(CLOSESIZE);
                                }
-yy161:
+yy163:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych <= '/') goto yy109;
-       if (yych <= '9') goto yy161;
+       if (yych <= '9') goto yy163;
        if (yych != '}') goto yy109;
        ++YYCURSOR;
        {
@@ -954,12 +960,12 @@ yy161:
                                        yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1));
                                        RETURN(CLOSESIZE);
                                }
-yy165:
+yy167:
        yyaccept = 7;
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych <= '/') goto yy155;
-       if (yych <= '9') goto yy161;
-       if (yych != '}') goto yy155;
+       if (yych <= '/') goto yy157;
+       if (yych <= '9') goto yy163;
+       if (yych != '}') goto yy157;
        ++YYCURSOR;
        {
                                        yylval.op = '*';
@@ -1010,20 +1016,20 @@ code:
        yych = *YYCURSOR;
        if (yych <= '&') {
                if (yych <= 0x0A) {
-                       if (yych <= 0x00) goto yy176;
-                       if (yych <= 0x09) goto yy178;
-                       goto yy174;
+                       if (yych <= 0x00) goto yy178;
+                       if (yych <= 0x09) goto yy180;
+                       goto yy176;
                } else {
-                       if (yych == '"') goto yy180;
-                       goto yy178;
+                       if (yych == '"') goto yy182;
+                       goto yy180;
                }
        } else {
                if (yych <= '{') {
-                       if (yych <= '\'') goto yy181;
-                       if (yych <= 'z') goto yy178;
-                       goto yy172;
+                       if (yych <= '\'') goto yy183;
+                       if (yych <= 'z') goto yy180;
+                       goto yy174;
                } else {
-                       if (yych != '}') goto yy178;
+                       if (yych != '}') goto yy180;
                }
        }
        ++YYCURSOR;
@@ -1040,7 +1046,7 @@ code:
                                        }
                                        goto code;
                                }
-yy172:
+yy174:
        ++YYCURSOR;
        {
                                        if (depth == 0)
@@ -1053,17 +1059,17 @@ yy172:
                                        }
                                        goto code;
                                }
-yy174:
+yy176:
        YYCTXMARKER = YYCURSOR + 1;
        ++YYCURSOR;
        if ((yych = *YYCURSOR) <= 0x0C) {
-               if (yych <= 0x08) goto yy175;
-               if (yych <= 0x0A) goto yy189;
+               if (yych <= 0x08) goto yy177;
+               if (yych <= 0x0A) goto yy191;
        } else {
-               if (yych <= 0x0D) goto yy189;
-               if (yych == ' ') goto yy189;
+               if (yych <= 0x0D) goto yy191;
+               if (yych == ' ') goto yy191;
        }
-yy175:
+yy177:
        {
                                        if (depth == 0)
                                        {
@@ -1084,7 +1090,7 @@ yy175:
                                        cline++;
                                        goto code;
                                }
-yy176:
+yy178:
        ++YYCURSOR;
        {
                                        if (cursor == eof)
@@ -1097,56 +1103,56 @@ yy176:
                                        }
                                        goto code;
                                }
-yy178:
+yy180:
        ++YYCURSOR;
-yy179:
+yy181:
        {
                                        goto code;
                                }
-yy180:
+yy182:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == 0x0A) goto yy179;
-       goto yy187;
-yy181:
+       if (yych == 0x0A) goto yy181;
+       goto yy189;
+yy183:
        yych = *(YYMARKER = ++YYCURSOR);
-       if (yych == 0x0A) goto yy179;
-       goto yy183;
-yy182:
+       if (yych == 0x0A) goto yy181;
+       goto yy185;
+yy184:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy183:
+yy185:
        if (yybm[0+yych] & 64) {
-               goto yy182;
+               goto yy184;
        }
-       if (yych <= '&') goto yy184;
-       if (yych <= '\'') goto yy178;
-       goto yy185;
-yy184:
+       if (yych <= '&') goto yy186;
+       if (yych <= '\'') goto yy180;
+       goto yy187;
+yy186:
        YYCURSOR = YYMARKER;
-       goto yy179;
-yy185:
+       goto yy181;
+yy187:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       if (yych == 0x0A) goto yy184;
-       goto yy182;
-yy186:
+       if (yych == 0x0A) goto yy186;
+       goto yy184;
+yy188:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy187:
+yy189:
        if (yybm[0+yych] & 128) {
-               goto yy186;
+               goto yy188;
        }
-       if (yych <= '!') goto yy184;
-       if (yych <= '"') goto yy178;
+       if (yych <= '!') goto yy186;
+       if (yych <= '"') goto yy180;
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       if (yych == 0x0A) goto yy184;
-       goto yy186;
-yy189:
+       if (yych == 0x0A) goto yy186;
+       goto yy188;
+yy191:
        ++YYCURSOR;
        YYCURSOR = YYCTXMARKER;
        {
@@ -1172,17 +1178,17 @@ comment:
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= ')') {
-               if (yych == 0x0A) goto yy196;
-               goto yy198;
+               if (yych == 0x0A) goto yy198;
+               goto yy200;
        } else {
-               if (yych <= '*') goto yy193;
-               if (yych == '/') goto yy195;
-               goto yy198;
+               if (yych <= '*') goto yy195;
+               if (yych == '/') goto yy197;
+               goto yy200;
        }
-yy193:
+yy195:
        ++YYCURSOR;
-       if ((yych = *YYCURSOR) == '/') goto yy201;
-yy194:
+       if ((yych = *YYCURSOR) == '/') goto yy203;
+yy196:
        {
                                        if(cursor == eof)
                                        {
@@ -1190,11 +1196,11 @@ yy194:
                                        }
                                        goto comment;
                                }
-yy195:
+yy197:
        yych = *++YYCURSOR;
-       if (yych == '*') goto yy199;
-       goto yy194;
-yy196:
+       if (yych == '*') goto yy201;
+       goto yy196;
+yy198:
        ++YYCURSOR;
        {
                                        if(cursor == eof)
@@ -1205,17 +1211,17 @@ yy196:
                                        cline++;
                                        goto comment;
                                }
-yy198:
+yy200:
        yych = *++YYCURSOR;
-       goto yy194;
-yy199:
+       goto yy196;
+yy201:
        ++YYCURSOR;
        {
                                        ++depth;
                                        fatal("ambiguous /* found");
                                        goto comment;
                                }
-yy201:
+yy203:
        ++YYCURSOR;
        {
                                        if(--depth == 0)
@@ -1271,52 +1277,52 @@ config:
        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
        yych = *YYCURSOR;
        if (yych <= 0x1F) {
-               if (yych != 0x09) goto yy209;
+               if (yych != 0x09) goto yy211;
        } else {
-               if (yych <= ' ') goto yy205;
-               if (yych == '=') goto yy207;
-               goto yy209;
+               if (yych <= ' ') goto yy207;
+               if (yych == '=') goto yy209;
+               goto yy211;
        }
-yy205:
+yy207:
        ++YYCURSOR;
        yych = *YYCURSOR;
-       goto yy214;
-yy206:
+       goto yy216;
+yy208:
        {
                                        goto config;
                                }
-yy207:
+yy209:
        ++YYCURSOR;
        yych = *YYCURSOR;
-       goto yy212;
-yy208:
+       goto yy214;
+yy210:
        {
                                        iscfg = 2;
                                        cur = cursor;
                                        RETURN('=');
                                }
-yy209:
+yy211:
        ++YYCURSOR;
        {
                                        fatal("missing '='");
                                }
-yy211:
+yy213:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy212:
+yy214:
        if (yybm[0+yych] & 128) {
-               goto yy211;
+               goto yy213;
        }
-       goto yy208;
-yy213:
+       goto yy210;
+yy215:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy214:
-       if (yych == 0x09) goto yy213;
-       if (yych == ' ') goto yy213;
-       goto yy206;
+yy216:
+       if (yych == 0x09) goto yy215;
+       if (yych == ' ') goto yy215;
+       goto yy208;
 }
 
 
@@ -1362,191 +1368,191 @@ value:
        yych = *YYCURSOR;
        if (yych <= '&') {
                if (yych <= 0x0D) {
-                       if (yych <= 0x08) goto yy223;
-                       if (yych <= 0x0A) goto yy217;
-                       if (yych <= 0x0C) goto yy223;
+                       if (yych <= 0x08) goto yy225;
+                       if (yych <= 0x0A) goto yy219;
+                       if (yych <= 0x0C) goto yy225;
                } else {
                        if (yych <= ' ') {
-                               if (yych <= 0x1F) goto yy223;
+                               if (yych <= 0x1F) goto yy225;
                        } else {
-                               if (yych == '"') goto yy225;
-                               goto yy223;
+                               if (yych == '"') goto yy227;
+                               goto yy225;
                        }
                }
        } else {
                if (yych <= '/') {
-                       if (yych <= '\'') goto yy227;
-                       if (yych == '-') goto yy220;
-                       goto yy223;
+                       if (yych <= '\'') goto yy229;
+                       if (yych == '-') goto yy222;
+                       goto yy225;
                } else {
                        if (yych <= '9') {
-                               if (yych <= '0') goto yy218;
-                               goto yy221;
+                               if (yych <= '0') goto yy220;
+                               goto yy223;
                        } else {
-                               if (yych != ';') goto yy223;
+                               if (yych != ';') goto yy225;
                        }
                }
        }
-yy217:
+yy219:
        {
                                        cur = cursor;
                                        yylval.str = new Str(token());
                                        iscfg = 0;
                                        return VALUE;
                                }
-yy218:
+yy220:
        ++YYCURSOR;
        if (yybm[0+(yych = *YYCURSOR)] & 8) {
-               goto yy223;
+               goto yy225;
        }
-yy219:
+yy221:
        {
                                        cur = cursor;
                                        yylval.number = atoi(token().to_string().c_str());
                                        iscfg = 0;
                                        return NUMBER;
                                }
-yy220:
+yy222:
        yych = *++YYCURSOR;
-       if (yych <= '0') goto yy224;
-       if (yych >= ':') goto yy224;
-yy221:
+       if (yych <= '0') goto yy226;
+       if (yych >= ':') goto yy226;
+yy223:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 4) {
-               goto yy221;
+               goto yy223;
        }
        if (yych <= 0x0D) {
-               if (yych <= 0x08) goto yy223;
-               if (yych <= 0x0A) goto yy219;
-               if (yych >= 0x0D) goto yy219;
+               if (yych <= 0x08) goto yy225;
+               if (yych <= 0x0A) goto yy221;
+               if (yych >= 0x0D) goto yy221;
        } else {
                if (yych <= ' ') {
-                       if (yych >= ' ') goto yy219;
+                       if (yych >= ' ') goto yy221;
                } else {
-                       if (yych == ';') goto yy219;
+                       if (yych == ';') goto yy221;
                }
        }
-yy223:
+yy225:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-yy224:
+yy226:
        if (yybm[0+yych] & 8) {
-               goto yy223;
+               goto yy225;
        }
-       goto yy217;
-yy225:
+       goto yy219;
+yy227:
        YYMARKER = ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 16) {
-               goto yy225;
+               goto yy227;
        }
        if (yych <= '!') {
-               if (yych == 0x0A) goto yy217;
-               goto yy235;
-       } else {
-               if (yych <= '"') goto yy223;
-               if (yych <= '[') goto yy235;
+               if (yych == 0x0A) goto yy219;
                goto yy237;
+       } else {
+               if (yych <= '"') goto yy225;
+               if (yych <= '[') goto yy237;
+               goto yy239;
        }
-yy227:
+yy229:
        YYMARKER = ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 32) {
-               goto yy227;
+               goto yy229;
        }
        if (yych <= '&') {
-               if (yych == 0x0A) goto yy217;
+               if (yych == 0x0A) goto yy219;
        } else {
-               if (yych <= '\'') goto yy223;
-               if (yych >= '\\') goto yy232;
+               if (yych <= '\'') goto yy225;
+               if (yych >= '\\') goto yy234;
        }
-yy229:
+yy231:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 64) {
-               goto yy229;
+               goto yy231;
        }
-       if (yych <= '&') goto yy231;
-       if (yych <= '\'') goto yy233;
-       goto yy234;
-yy231:
+       if (yych <= '&') goto yy233;
+       if (yych <= '\'') goto yy235;
+       goto yy236;
+yy233:
        YYCURSOR = YYMARKER;
-       goto yy217;
-yy232:
+       goto yy219;
+yy234:
        YYMARKER = ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych <= 0x0D) {
                if (yych <= 0x09) {
-                       if (yych <= 0x08) goto yy227;
-                       goto yy229;
+                       if (yych <= 0x08) goto yy229;
+                       goto yy231;
                } else {
-                       if (yych <= 0x0A) goto yy217;
-                       if (yych <= 0x0C) goto yy227;
-                       goto yy229;
+                       if (yych <= 0x0A) goto yy219;
+                       if (yych <= 0x0C) goto yy229;
+                       goto yy231;
                }
        } else {
                if (yych <= ' ') {
-                       if (yych <= 0x1F) goto yy227;
-                       goto yy229;
+                       if (yych <= 0x1F) goto yy229;
+                       goto yy231;
                } else {
-                       if (yych == ';') goto yy229;
-                       goto yy227;
+                       if (yych == ';') goto yy231;
+                       goto yy229;
                }
        }
-yy233:
+yy235:
        yych = *++YYCURSOR;
-       goto yy217;
-yy234:
+       goto yy219;
+yy236:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       if (yych == 0x0A) goto yy231;
-       goto yy229;
-yy235:
+       if (yych == 0x0A) goto yy233;
+       goto yy231;
+yy237:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yybm[0+yych] & 128) {
-               goto yy235;
+               goto yy237;
        }
-       if (yych <= '!') goto yy231;
-       if (yych <= '"') goto yy233;
-       goto yy238;
-yy237:
+       if (yych <= '!') goto yy233;
+       if (yych <= '"') goto yy235;
+       goto yy240;
+yy239:
        YYMARKER = ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
        if (yych <= 0x0D) {
                if (yych <= 0x09) {
-                       if (yych <= 0x08) goto yy225;
-                       goto yy235;
+                       if (yych <= 0x08) goto yy227;
+                       goto yy237;
                } else {
-                       if (yych <= 0x0A) goto yy217;
-                       if (yych <= 0x0C) goto yy225;
-                       goto yy235;
+                       if (yych <= 0x0A) goto yy219;
+                       if (yych <= 0x0C) goto yy227;
+                       goto yy237;
                }
        } else {
                if (yych <= ' ') {
-                       if (yych <= 0x1F) goto yy225;
-                       goto yy235;
+                       if (yych <= 0x1F) goto yy227;
+                       goto yy237;
                } else {
-                       if (yych == ';') goto yy235;
-                       goto yy225;
+                       if (yych == ';') goto yy237;
+                       goto yy227;
                }
        }
-yy238:
+yy240:
        ++YYCURSOR;
        if (YYLIMIT == YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       if (yych == 0x0A) goto yy231;
-       goto yy235;
+       if (yych == 0x0A) goto yy233;
+       goto yy237;
 }
 
 }
index 4d3b909aefdfb4ebdc488ebeae8c65a8bccd23ae..545483698f90eb68cbdd132e01dc06ad57322f64 100644 (file)
@@ -49,7 +49,8 @@
      STRING = 265,
      CONFIG = 266,
      VALUE = 267,
-     NUMBER = 268
+     NUMBER = 268,
+     SETUP = 269
    };
 #endif
 /* Tokens.  */
 #define CONFIG 266
 #define VALUE 267
 #define NUMBER 268
+#define SETUP 269
 
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 106 "parser.y"
+#line 127 "parser.y"
 {
        re2c::Symbol    *symbol;
        re2c::RegExp    *regexp;
@@ -82,7 +84,7 @@ typedef union YYSTYPE
        re2c::CondList  *clist;
 }
 /* Line 1489 of yacc.c.  */
-#line 86 "y.tab.h"
+#line 88 "y.tab.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index 8fbc09487d07d74428c736e69a21f9be524e51d8..aebe97d3d59afd1b3ea513d0606ad7e12525e405 100644 (file)
@@ -684,6 +684,11 @@ void Rule::emit(std::ostream &o, uint ind, bool &, const std::string& condName)
 
        RuleLine rl(*rule);
 
+       if (!yySetupRule.empty() && !rule->code->autogen)
+       {
+               o << indent(ind) << yySetupRule << "\n";
+       }
+
        o << file_info(sourceFileInfo, &rl);
        o << indent(ind);
        if (rule->code->autogen)
index fd04656ddb09a03b95873280b6038e7a9ce16e30..4f825ac4fa1ba02b41157560595ccebfbd394518 100644 (file)
@@ -51,6 +51,7 @@ extern std::string yychConversion;
 extern std::string yyFillLength;
 extern std::string yySetConditionParam;
 extern std::string yySetStateParam;
+extern std::string yySetupRule;
 extern uint maxFill;
 extern uint next_label;
 extern uint cGotoThreshold;
index 531844269773cf4692b1a672135087c916d53b14..70294dc85c773bce299d5107823d4a75c15dba9d 100755 (executable)
@@ -81,9 +81,10 @@ fixes which were incorporated. <a href=
 <hr />
 <h1>Changelog</h1>
 <h2>2007-??-??: 0.13.2</h2>
-<li>Added support for '=>' style rules.</li>
+<li>Added support for '&lt;!...&gt;' to enable rule setup.</li>
+<li>Added support for '=&gt;' style rules.</li>
 <li>Added support for ':=' style rules.</li>
-<li>Added support for ':=>' style rules.</li>
+<li>Added support for ':=&gt;' style rules.</li>
 <li>Added re2c:cond:divider and re2c:con:goto inplace configuration.</li>
 <li>Fixed code generation to emit space after 'if'.</li>
 <ul>
index 8ab6bd2a85a1a82508d909a704b845a3f9c63401..e8b1091a55d55a602451172481011df64b40267c 100755 (executable)
@@ -313,7 +313,8 @@ rules can use ':=>' as a shortcut to automatically generate code that not only
 sets the new condition state but also continues execution with the new state. A
 shortcut rule should not be used in a loop where there is code between the start
 of the loop and the <b>re2c</b> block unless <i>re2c:cond:goto</i> is changed
-to '<i>continue;</i>'.
+to '<i>continue;</i>'. If code is necessary before all rule (though not simple
+jumps) you can doso by using &lt;! pseudo-rules.
 </p>
 <dl compact="compact">
 <dd>&lt;<i>condition-list</i>&gt; <i>regular-expression</i> { <i>C/C++ code</i> }</dd>
@@ -331,6 +332,10 @@ to '<i>continue;</i>'.
 <dd>&lt;&gt; =&gt; <i>condition</i> { <i>C/C++ code</i> }</dd>
 <dd>&lt;&gt; =&gt; <i>condition</i> := <i>C/C++ code</i></dd>
 <dd>&lt;&gt; :=&gt; <i>condition</i></dd>
+<dd>&lt;!<i>condition-list</i>&gt; { <i>C/C++ code</i> }</dd>
+<dd>&lt;!<i>condition-list</i>&gt; := <i>C/C++ code</i></dd>
+<dd>&lt;!*&gt; { <i>C/C++ code</i> }</dd>
+<dd>&lt;!*&gt; := <i>C/C++ code</i></dd>
 </dl>
 <p>Named definitions are of the form:</p>
 <dl compact="compact">
index 9842d7e930ffd6855c0296edf600f9d69debfa2e..c75545167a6e348b765448a67957427df1e1e0d3 100644 (file)
@@ -67,6 +67,7 @@ std::string yychConversion("");
 std::string yyFillLength("@@");
 std::string yySetConditionParam("@@");
 std::string yySetStateParam("@@");
+std::string yySetupRule("");
 uint maxFill = 1;
 uint next_label = 0;
 uint cGotoThreshold = 9;
index fae174f7e811cafa218b7d6823fca5a54d0b95c8..aecc9bbca3209aa0b6c6b8560ad0e4dcc8d9d855 100644 (file)
@@ -10,6 +10,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <iostream>
+#include <set>
 
 #include "globals.h"
 #include "parser.h"
@@ -31,6 +32,7 @@ static re2c::RegExpMap  specMap;
 static RegExp           *spec, *specNone = NULL;
 static RuleOpList       specStar;
 static Scanner          *in = NULL;
+static StringMap        ruleSetupMap;
 
 /* Bison version 1.875 emits a definition that is not working
  * with several g++ version. Hence we disable it here.
@@ -99,6 +101,25 @@ void context_rule(CondList *clist, RegExp *expr, RegExp *look, Str *newcond, Tok
        delete code;
 }
 
+void setup_rule(CondList *clist, Token *code)
+{
+       assert(clist);
+       assert(code);
+       context_check(clist);
+       if (bFirstPass) {
+               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               {
+                       if (ruleSetupMap.find(*it) != ruleSetupMap.end())
+                       {
+                               in->fatalf("code to setup rule '%s' is already defined", it->c_str());
+                       }
+                       ruleSetupMap[*it] = code->text.to_string();
+               }
+       }
+       delete clist;
+       delete code;
+}
+
 %}
 
 %start spec
@@ -115,9 +136,9 @@ void context_rule(CondList *clist, RegExp *expr, RegExp *look, Str *newcond, Tok
 };
 
 %token         CLOSESIZE       CLOSE   STAR    NOCOND  ID      CODE    RANGE   STRING
-%token         CONFIG  VALUE   NUMBER
+%token         CONFIG          VALUE   NUMBER  SETUP
 
-%type  <op>            CLOSE   STAR
+%type  <op>            CLOSE   STAR    SETUP
 %type  <op>            close
 %type  <extop>         CLOSESIZE
 %type  <symbol>        ID
@@ -247,6 +268,16 @@ rule:
                        delete $3;
                        $$ = specNone = new RuleOp(new NullOp(), new NullOp(), token, accept++);
                }
+       |       SETUP STAR '>' CODE
+               {
+                       CondList *clist = new CondList();
+                       clist->insert("*");
+                       setup_rule(clist, $4);
+               }
+       |       SETUP cond '>' CODE
+               {
+                       setup_rule($2, $4);
+               }
 ;
 
 cond:
@@ -430,20 +461,21 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
        o << " */\n";
        o << sourceFileInfo;
        
-       while(i.echo())
+       while (i.echo())
        {
                bool bPrologBrace = false;
                yyparse();
                if (cFlag)
                {
                        RegExpMap::iterator it;
+                       StringMap::const_iterator itRuleSetup;
 
                        if (!specStar.empty())
                        {
-                               for(it = specMap.begin(); it != specMap.end(); ++it)
+                               for (it = specMap.begin(); it != specMap.end(); ++it)
                                {
                                        assert(it->second.second);
-                                       for(RuleOpList::const_iterator itOp = specStar.begin(); itOp != specStar.end(); ++itOp)
+                                       for (RuleOpList::const_iterator itOp = specStar.begin(); itOp != specStar.end(); ++itOp)
                                        {
                                                it->second.second = mkAlt((*itOp)->copy(accept++), it->second.second);
                                        }
@@ -461,16 +493,46 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                        {
                                // We reserved 0 for specNone but it is not present,
                                // so we can decrease all specs.
-                               for(it = specMap.begin(); it != specMap.end(); ++it)
+                               for (it = specMap.begin(); it != specMap.end(); ++it)
                                {
                                        it->second.first--;
                                }
                        }
 
                        size_t nCount = specMap.size();
-                       for(it = specMap.begin(); it != specMap.end(); ++it)
+
+                       for (itRuleSetup = ruleSetupMap.begin(); itRuleSetup != ruleSetupMap.end(); ++itRuleSetup)
+                       {
+                               if (itRuleSetup->first != "*" && specMap.find(itRuleSetup->first) == specMap.end())
+                               {
+                                       in->fatalf("Setup for non existing rule '%s' found", itRuleSetup->first.c_str());
+                               }
+                       }
+                       if (nCount < (ruleSetupMap.find("*") == ruleSetupMap.end() ? ruleSetupMap.size() : ruleSetupMap.size()))
+                       {
+                               in->fatalf("Setup for all rules with '*' not possible when all rules are setup explicitly");
+                       }
+                       for (it = specMap.begin(); it != specMap.end(); ++it)
                        {
                                assert(it->second.second);
+
+                               itRuleSetup = ruleSetupMap.find(it->first);                             
+                               if (itRuleSetup != ruleSetupMap.end())
+                               {
+                                       yySetupRule = itRuleSetup->second;
+                               }
+                               else
+                               {
+                                       itRuleSetup = ruleSetupMap.find("*");
+                                       if (itRuleSetup != ruleSetupMap.end())
+                                       {
+                                               yySetupRule = itRuleSetup->second;
+                                       }
+                                       else
+                                       {
+                                               yySetupRule = "";
+                                       }
+                               }
                                genCode(o, topIndent, it->second.second, &specMap, it->first, !--nCount, bPrologBrace);
                        }
                        if (h)
@@ -482,7 +544,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                genTypes(typesInline, 0, specMap);
                        }
                }
-               else if(spec)
+               else if (spec)
                {
                        genCode(o, topIndent, spec, NULL, "", 0, bPrologBrace);
                }
index a8361879b7ad88993d72f405a1496e9755b64ef8..8bfd3297fb02995f5064b9113484366772b94a6b 100644 (file)
--- a/re2c/re.h
+++ b/re2c/re.h
@@ -496,6 +496,7 @@ typedef std::pair<int, RegExp*>         NRegExp;
 typedef std::map<std::string, NRegExp>  RegExpMap;
 typedef std::vector<std::string>        RegExpIndices;
 typedef std::list<RuleOp*>              RuleOpList;
+typedef std::map<std::string, std::string> StringMap;
 
 extern void genCode(std::ostream&, uint&, RegExp*, const RegExpMap*, const std::string&, bool, bool&);
 extern void genGetStateGoto(std::ostream&, uint&, uint);
index d386f8ddbb57e426f59ab63c9cc2ab076b7f656c..d05bad07e638d53ff1c203e5862b7abc269ef351 100644 (file)
@@ -355,7 +355,8 @@ rules can use ':=>' as a shortcut to automatically generate code that not only
 sets the new condition state but also continues execution with the new state. A
 shortcut rule should not be used in a loop where there is code between the start
 of the loop and the \*(re block unless \fIre2c:cond:goto\fP is changed
-to '\fIcontinue;\fP'.
+to '\fIcontinue;\fP'. If code is necessary before all rule (though not simple
+jumps) you can doso by using <! pseudo-rules.
 .P
 .RS
 \fC<\fP\fIcondition-list\fP\fC>\fP \fI\*(rx\fP \fC{\fP \fIC/C++ code\fP \fC}\fP
@@ -387,6 +388,14 @@ to '\fIcontinue;\fP'.
 \fC<>\fP \fC=>\fP \fP\fIcondition\fP \fC:=\fP \fIC/C++ code\fP
 .P
 \fC<>\fP \fC:=>\fP \fP\fIcondition\fP
+.P
+\fC<!\fIcondition-list\fP>\fP \fC{\fP \fIC/C++ code\fP \fC}\fP
+.P
+\fC<!\fIcondition-list\fP>\fP \fC:=\fP \fIC/C++ code\fP
+.P
+\fC<!*>\fP \fC{\fP \fIC/C++ code\fP \fC}\fP
+.P
+\fC<!*>\fP \fC:=\fP \fIC/C++ code\fP
 .RE
 .LP
 Named definitions are of the form:
index 07f6b59993e1a8cad4023d2aa4a00951ce3f2b6a..4745f71c045b66d28d3525743b48e1aed4570866 100644 (file)
@@ -307,6 +307,9 @@ scan:
        "<>" / (ws* ("{" | "=>" | ":=")) {
                                        RETURN(NOCOND);
                                }
+       "<!"            {
+                                       RETURN(SETUP);
+                               }
        [<>,()|=;/\\]   {
                                        RETURN(*tok);
                                }
diff --git a/re2c/test/cond_error_09.c.c b/re2c/test/cond_error_09.c.c
new file mode 100755 (executable)
index 0000000..dde066b
--- /dev/null
@@ -0,0 +1 @@
+re2c: error: line 6, column 6: code to setup rule 'a' is already defined
diff --git a/re2c/test/cond_error_09.c.re b/re2c/test/cond_error_09.c.re
new file mode 100755 (executable)
index 0000000..e54f7cb
--- /dev/null
@@ -0,0 +1,8 @@
+/*!re2c
+
+<a>"a" { return 1; }
+<b>"b" { return 2; }
+<!a> { printf("foo"); }
+<!a> := printf("bar");
+
+*/
diff --git a/re2c/test/cond_error_10.c.c b/re2c/test/cond_error_10.c.c
new file mode 100755 (executable)
index 0000000..1cb5763
--- /dev/null
@@ -0,0 +1 @@
+re2c: error: line 8, column 1: Setup for non existing rule 'c' found
diff --git a/re2c/test/cond_error_10.c.re b/re2c/test/cond_error_10.c.re
new file mode 100755 (executable)
index 0000000..32af77b
--- /dev/null
@@ -0,0 +1,8 @@
+/*!re2c
+
+<a>"a" { return 1; }
+<b>"b" { return 2; }
+<!a> { printf("foo"); }
+<!c> := printf("bar");
+
+*/
diff --git a/re2c/test/cond_error_11.c.c b/re2c/test/cond_error_11.c.c
new file mode 100755 (executable)
index 0000000..45a51bb
--- /dev/null
@@ -0,0 +1 @@
+re2c: error: line 9, column 1: Setup for all rules with '*' not possible when all rules are setup explicitly
diff --git a/re2c/test/cond_error_11.c.re b/re2c/test/cond_error_11.c.re
new file mode 100755 (executable)
index 0000000..1f99cd4
--- /dev/null
@@ -0,0 +1,9 @@
+/*!re2c
+
+<a>"a" { return 1; }
+<b>"b" { return 2; }
+<!a> { printf("foo"); }
+<!b> := printf("bar");
+<!*> := printf("baz");
+
+*/
diff --git a/re2c/test/condition_15.csif.c b/re2c/test/condition_15.csif.c
new file mode 100755 (executable)
index 0000000..acaf5fa
--- /dev/null
@@ -0,0 +1,383 @@
+/* Generated by re2c */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define        BSIZE   8192
+
+
+enum ScanContition {
+       EStateNormal,
+       EStateComment,
+       EStateSkiptoeol,
+       EStateString,
+};
+
+
+typedef struct Scanner
+{
+       FILE                        *fp;
+       unsigned char       *cur, *tok, *lim, *eof;
+       unsigned char       buffer[BSIZE];
+       unsigned char       yych;
+       enum ScanContition  cond;
+       int                 state;
+} Scanner;
+
+size_t fill(Scanner *s, size_t len)
+{
+       size_t got = ~0, cnt;
+
+       if (!s->eof && s->lim - s->tok < len)
+       {
+               if (s->tok > s->buffer)
+               {
+                       cnt = s->tok - s->buffer;
+                       memcpy(s->buffer, s->tok, s->lim - s->tok);
+                       s->tok -= cnt;
+                       s->cur -= cnt;
+                       s->lim -= cnt;
+                       cnt = &s->buffer[BSIZE] - s->lim;
+               }
+               else
+               {
+                       cnt = BSIZE;
+               }
+               if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
+               {
+                       s->eof = &s->lim[got];
+               }
+               s->lim += got;
+       }
+       if (s->eof && s->cur + len > s->eof)
+       {
+               return ~0; /* not enough input data */
+       }
+       return got;
+}
+
+size_t init(Scanner *s)
+{
+       s->cur = s->tok = s->lim = s->buffer;
+       s->eof = 0;
+       s->cond = EStateNormal;
+       s->state = -1;
+
+       return fill(s, 0);
+}
+
+void fputl(const char *s, size_t len, FILE *stream)
+{
+       while(len-- > 0)
+       {
+               fputc(*s++, stream);
+       }
+}
+
+void scan(Scanner *s)
+{
+       s->tok = s->cur;
+
+       switch (s->state) {
+       default: goto yy0;
+       case 0: goto yyFillLabel0;
+       case 1: goto yyFillLabel1;
+       case 2: goto yyFillLabel2;
+       case 3: goto yyFillLabel3;
+       }
+       for(;;)
+       {
+               s->tok = s->cur;
+
+
+yy0:
+               if (s->cond < 2) {
+                       if (s->cond < 1) {
+                               goto yyc_Normal;
+                       } else {
+                               goto yyc_Comment;
+                       }
+               } else {
+                       if (s->cond < 3) {
+                               goto yyc_Skiptoeol;
+                       } else {
+                               goto yyc_String;
+                       }
+               }
+/* *********************************** */
+yyc_Comment:
+
+               s->state = 0;
+               if ((s->lim - s->cur) < 2) if (fill(s, 2) == ~0) break;
+yyFillLabel0:
+               s->yych = *s->cur;
+               if (s->yych != '*') goto yy4;
+               ++s->cur;
+               if ((s->yych = *s->cur) == '/') goto yy5;
+yy3:
+               continue;
+yy4:
+               s->yych = *++s->cur;
+               goto yy3;
+yy5:
+               ++s->cur;
+               s->cond = EStateNormal;
+               continue;
+/* *********************************** */
+yyc_Normal:
+               s->state = 1;
+               if ((s->lim - s->cur) < 4) if (fill(s, 4) == ~0) break;
+yyFillLabel1:
+               s->yych = *s->cur;
+               if (s->yych <= '\'') {
+                       if (s->yych == '"') goto yy13;
+                       if (s->yych <= '&') goto yy15;
+                       goto yy12;
+               } else {
+                       if (s->yych <= '/') {
+                               if (s->yych <= '.') goto yy15;
+                               goto yy11;
+                       } else {
+                               if (s->yych != '?') goto yy15;
+                       }
+               }
+               s->yych = *(s->tok = ++s->cur);
+               if (s->yych == '?') goto yy26;
+yy10:
+               fprintf(stderr, "Normal\n");
+               fputc(s->cur[-1], stdout);
+               continue;
+yy11:
+               s->yych = *++s->cur;
+               if (s->yych == '*') goto yy24;
+               if (s->yych == '/') goto yy22;
+               goto yy10;
+yy12:
+               s->yych = *(s->tok = ++s->cur);
+               if (s->yych == '"') goto yy16;
+               if (s->yych == '\\') goto yy18;
+               goto yy10;
+yy13:
+               ++s->cur;
+               s->cond = EStateString;
+               fprintf(stderr, "Normal\n");
+               fputc(s->cur[-1], stdout);
+               continue;
+yy15:
+               s->yych = *++s->cur;
+               goto yy10;
+yy16:
+               s->yych = *++s->cur;
+               if (s->yych == '\'') goto yy20;
+yy17:
+               s->cur = s->tok;
+               goto yy10;
+yy18:
+               s->yych = *++s->cur;
+               if (s->yych != '"') goto yy17;
+               s->yych = *++s->cur;
+               if (s->yych != '\'') goto yy17;
+yy20:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputl("'\"'", 3, stdout);
+               continue;
+yy22:
+               ++s->cur;
+               s->cond = EStateSkiptoeol;
+               continue;
+yy24:
+               ++s->cur;
+               s->cond = EStateComment;
+               continue;
+yy26:
+               s->yych = *++s->cur;
+               switch (s->yych) {
+               case '!':       goto yy41;
+               case '\'':      goto yy39;
+               case '(':       goto yy27;
+               case ')':       goto yy29;
+               case '-':       goto yy43;
+               case '/':       goto yy37;
+               case '<':       goto yy31;
+               case '=':       goto yy35;
+               case '>':       goto yy33;
+               default:        goto yy17;
+               }
+yy27:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('[', stdout);
+               continue;
+yy29:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc(']', stdout);
+               continue;
+yy31:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('{', stdout);
+               continue;
+yy33:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('}', stdout);
+               continue;
+yy35:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('#', stdout);
+               continue;
+yy37:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('\\', stdout);
+               continue;
+yy39:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('^', stdout);
+               continue;
+yy41:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('|', stdout);
+               continue;
+yy43:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputc('~', stdout);
+               continue;
+/* *********************************** */
+yyc_Skiptoeol:
+               s->state = 2;
+               if ((s->lim - s->cur) < 5) if (fill(s, 5) == ~0) break;
+yyFillLabel2:
+               s->yych = *s->cur;
+               if (s->yych <= 0x0D) {
+                       if (s->yych == 0x0A) goto yy51;
+                       if (s->yych <= 0x0C) goto yy53;
+                       goto yy50;
+               } else {
+                       if (s->yych <= '?') {
+                               if (s->yych <= '>') goto yy53;
+                       } else {
+                               if (s->yych == '\\') goto yy49;
+                               goto yy53;
+                       }
+               }
+               s->yych = *(s->tok = ++s->cur);
+               if (s->yych == '?') goto yy60;
+yy48:
+               continue;
+yy49:
+               s->yych = *(s->tok = ++s->cur);
+               if (s->yych == 0x0A) goto yy58;
+               if (s->yych == 0x0D) goto yy56;
+               goto yy48;
+yy50:
+               s->yych = *++s->cur;
+               if (s->yych == 0x0A) goto yy54;
+               goto yy48;
+yy51:
+               ++s->cur;
+               s->cond = EStateNormal;
+               fprintf(stderr, "Comment\n");
+               fputc('\n', stdout);
+               continue;
+yy53:
+               s->yych = *++s->cur;
+               goto yy48;
+yy54:
+               ++s->cur;
+               s->cond = EStateNormal;
+               fprintf(stderr, "Comment\n");
+               fputc('\r', stdout);
+               fputc('\n', stdout);
+               continue;
+yy56:
+               s->yych = *++s->cur;
+               if (s->yych == 0x0A) goto yy58;
+yy57:
+               s->cur = s->tok;
+               goto yy48;
+yy58:
+               ++s->cur;
+               continue;
+yy60:
+               s->yych = *++s->cur;
+               if (s->yych != '/') goto yy57;
+               s->yych = *++s->cur;
+               if (s->yych == 0x0A) goto yy63;
+               if (s->yych != 0x0D) goto yy57;
+               s->yych = *++s->cur;
+               if (s->yych != 0x0A) goto yy57;
+yy63:
+               ++s->cur;
+               continue;
+/* *********************************** */
+yyc_String:
+               s->state = 3;
+               if ((s->lim - s->cur) < 2) if (fill(s, 2) == ~0) break;
+yyFillLabel3:
+               s->yych = *s->cur;
+               if (s->yych == '"') goto yy69;
+               if (s->yych != '\\') goto yy71;
+               ++s->cur;
+               if ((s->yych = *s->cur) != 0x0A) goto yy72;
+yy68:
+               fprintf(stderr, "Normal\n");
+               fputc(s->cur[-1], stdout);
+               continue;
+yy69:
+               ++s->cur;
+               s->cond = EStateNormal;
+               fprintf(stderr, "Normal\n");
+               fputc(s->cur[-1], stdout);
+               continue;
+yy71:
+               s->yych = *++s->cur;
+               goto yy68;
+yy72:
+               ++s->cur;
+               fprintf(stderr, "Normal\n");
+               fputl((const char*)s->cur-2, 2, stdout);
+               continue;
+
+       }
+}
+
+int main(int argc, char **argv)
+{
+       Scanner in;
+
+       if (argc != 2)
+       {
+               fprintf(stderr, "%s <file>\n", argv[0]);
+               return 1;;
+       }
+
+       memset((char*) &in, 0, sizeof(in));
+
+       if (!strcmp(argv[1], "-"))
+       {
+               in.fp = stdin;
+       }
+       else if ((in.fp = fopen(argv[1], "r")) == NULL)
+       {
+               fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+               return 1;
+       }
+
+       if (init(&in) > 0)
+       {
+               scan(&in);
+       }
+
+       if (in.fp != stdin)
+       {
+               fclose(in.fp);
+       }
+       return 0;
+}
diff --git a/re2c/test/condition_15.csif.re b/re2c/test/condition_15.csif.re
new file mode 100755 (executable)
index 0000000..323b3e8
--- /dev/null
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define        BSIZE   8192
+
+/*!types:re2c */
+
+typedef struct Scanner
+{
+       FILE                        *fp;
+       unsigned char       *cur, *tok, *lim, *eof;
+       unsigned char       buffer[BSIZE];
+       unsigned char       yych;
+       enum ScanContition  cond;
+       int                 state;
+} Scanner;
+
+size_t fill(Scanner *s, size_t len)
+{
+       size_t got = ~0, cnt;
+
+       if (!s->eof && s->lim - s->tok < len)
+       {
+               if (s->tok > s->buffer)
+               {
+                       cnt = s->tok - s->buffer;
+                       memcpy(s->buffer, s->tok, s->lim - s->tok);
+                       s->tok -= cnt;
+                       s->cur -= cnt;
+                       s->lim -= cnt;
+                       cnt = &s->buffer[BSIZE] - s->lim;
+               }
+               else
+               {
+                       cnt = BSIZE;
+               }
+               if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt)
+               {
+                       s->eof = &s->lim[got];
+               }
+               s->lim += got;
+       }
+       if (s->eof && s->cur + len > s->eof)
+       {
+               return ~0; /* not enough input data */
+       }
+       return got;
+}
+
+size_t init(Scanner *s)
+{
+       s->cur = s->tok = s->lim = s->buffer;
+       s->eof = 0;
+       s->cond = EStateNormal;
+       s->state = -1;
+
+       return fill(s, 0);
+}
+
+void fputl(const char *s, size_t len, FILE *stream)
+{
+       while(len-- > 0)
+       {
+               fputc(*s++, stream);
+       }
+}
+
+void scan(Scanner *s)
+{
+       s->tok = s->cur;
+/*!re2c
+re2c:define:YYGETSTATE       = "s->state";
+re2c:define:YYGETSTATE:naked = 1;
+re2c:define:YYCONDTYPE       = ScanContition;
+re2c:indent:top              = 1;
+re2c:cond:goto               = "continue;";
+*/
+/*!getstate:re2c */
+       for(;;)
+       {
+               s->tok = s->cur;
+/*!re2c
+
+re2c:define:YYCTYPE          = "unsigned char";
+re2c:define:YYCURSOR         = s->cur;
+re2c:define:YYLIMIT          = s->lim;
+re2c:define:YYMARKER         = s->tok;
+re2c:define:YYFILL@len       = #;
+re2c:define:YYFILL:naked     = 1;
+re2c:define:YYFILL           = "if (fill(s, #) == ~0) break;";
+re2c:define:YYSETSTATE@state = #;
+re2c:define:YYSETSTATE       = "s->state = #;";
+re2c:define:YYSETCONDITION       = "s->cond = #;";
+re2c:define:YYSETCONDITION@cond  = #;
+re2c:define:YYGETCONDITION       = s->cond;
+re2c:define:YYGETCONDITION:naked = 1;
+re2c:variable:yych           = s->yych;
+re2c:yych:emit               = 0;
+re2c:indent:top              = 2;
+re2c:condenumprefix          = EState;
+
+<Normal>       "??(" :=
+               fputc('[', stdout);
+               continue;
+<Normal>       "??)" :=
+               fputc(']', stdout);
+               continue;
+<Normal>       "??<" :=
+               fputc('{', stdout);
+               continue;
+<Normal>       "??>" :=
+               fputc('}', stdout);
+               continue;
+<Normal>       "??=" :=
+               fputc('#', stdout);
+               continue;
+<Normal>       "??/" :=
+               fputc('\\', stdout);
+               continue;
+<Normal>       "??'" :=
+               fputc('^', stdout);
+               continue;
+<Normal>       "??!" :=
+               fputc('|', stdout);
+               continue;
+<Normal>       "??-" :=
+               fputc('~', stdout);
+               continue;
+<Normal>       "/*" :=> Comment
+<Normal>       "//" :=> Skiptoeol
+<Normal>       "'\\\"'"|"'\"'" :=
+               fputl("'\"'", 3, stdout);
+               continue;
+<Normal>       '"' => String :=
+               fputc(s->cur[-1], stdout);
+               continue;
+<Normal>       [^] :=
+               fputc(s->cur[-1], stdout);
+               continue;
+<Comment>      "*" "/" :=> Normal
+<Comment>      [^] :=> Comment
+<Skiptoeol>    "??/" "\r"? "\n" :=> Skiptoeol
+<Skiptoeol>    "\\" "\r"? "\n" :=> Skiptoeol
+<Skiptoeol>    "\r" "\n" => Normal :=
+               fputc('\r', stdout);
+               fputc('\n', stdout);
+               continue;
+<Skiptoeol>    "\n" => Normal :=
+               fputc('\n', stdout);
+               continue;
+<Skiptoeol>    [^] :=> Skiptoeol
+<String>       '\\' . :=
+               fputl((const char*)s->cur-2, 2, stdout);
+               continue;
+<String>       '"' => Normal :=
+               fputc(s->cur[-1], stdout);
+               continue;
+<String>       [^] :=
+               fputc(s->cur[-1], stdout);
+               continue;
+<!*>                                   := fprintf(stderr, "Normal\n");
+<!Comment,Skiptoeol>   := fprintf(stderr, "Comment\n");
+*/
+       }
+}
+
+int main(int argc, char **argv)
+{
+       Scanner in;
+
+       if (argc != 2)
+       {
+               fprintf(stderr, "%s <file>\n", argv[0]);
+               return 1;;
+       }
+
+       memset((char*) &in, 0, sizeof(in));
+
+       if (!strcmp(argv[1], "-"))
+       {
+               in.fp = stdin;
+       }
+       else if ((in.fp = fopen(argv[1], "r")) == NULL)
+       {
+               fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+               return 1;
+       }
+
+       if (init(&in) > 0)
+       {
+               scan(&in);
+       }
+
+       if (in.fp != stdin)
+       {
+               fclose(in.fp);
+       }
+       return 0;
+}