Bump to 1.14.1
[platform/upstream/augeas.git] / src / lexer.l
1 /* Scanner for config specs   -*- C -*- */
2 %option 8bit never-interactive yylineno
3 %option bison-bridge bison-locations
4 %option reentrant noyywrap
5 %option warn nodefault
6 %option outfile="lex.yy.c" prefix="augl_"
7 %option noinput nounput
8
9 %top{
10 /* config.h must precede flex's inclusion of <stdio.h>
11    in order for its _GNU_SOURCE definition to take effect.  */
12 #include <config.h>
13 }
14
15 %{
16 #include "syntax.h"
17 #include "errcode.h"
18
19 typedef struct info YYLTYPE;
20 #define YYLTYPE_IS_DECLARED 1
21
22 #include "parser.h"
23
24 /* Advance of NUM lines. */
25 # define LOCATION_LINES(Loc, Num)             \
26   (Loc).last_column = 0;                      \
27   (Loc).last_line += Num;
28
29 /* Restart: move the first cursor to the last position. */
30 # define LOCATION_STEP(Loc)                   \
31   (Loc).first_column = (Loc).last_column;     \
32   (Loc).first_line = (Loc).last_line;
33
34 /* The lack of reference counting for filename is intentional */
35 #define YY_USER_ACTION                                            \
36   do {                                                            \
37      yylloc->last_column += yyleng;                               \
38      yylloc->filename = augl_get_info(yyscanner)->filename;       \
39      yylloc->error = augl_get_info(yyscanner)->error;             \
40    } while(0);
41
42 #define YY_USER_INIT LOCATION_STEP(*yylloc)
43
44 #define YY_EXTRA_TYPE struct state *
45
46 int augl_init_lexer(struct state *state, yyscan_t * scanner);
47 void augl_close_lexer(yyscan_t *scanner);
48 struct info *augl_get_info(yyscan_t yyscanner);
49
50 static void loc_update(YYLTYPE *yylloc, const char *s, int len) {
51   for (int i=0; i < len; i++) {
52     if (s[i] == '\n') {
53       LOCATION_LINES(*yylloc, 1);
54     }
55   }
56 }
57
58 static char *regexp_literal(const char *s, int len) {
59   char *u = unescape(s, len, RX_ESCAPES);
60
61   if (u == NULL)
62     return NULL;
63
64   size_t u_len = strlen(u);
65   regexp_c_locale(&u, &u_len);
66
67   return u;
68 }
69 %}
70
71 DIGIT [0-9]
72 UID    [A-Z][A-Za-z0-9_]*
73 LID    [a-z_][A-Za-z0-9_]*
74 LETREC   let[ \t]+rec
75 WS     [ \t\n]
76 QID    {UID}\.{LID}
77 ARROW  ->
78
79 %s COMMENT
80
81 %%
82 <*>
83 {
84   [ \t]*        LOCATION_STEP(*yylloc);
85   \n+           LOCATION_LINES(*yylloc, yyleng); LOCATION_STEP(*yylloc);
86   (\r\n)+       LOCATION_LINES(*yylloc, yyleng/2); LOCATION_STEP(*yylloc);
87 }
88
89 <INITIAL>
90 {
91   \"([^\\\"]|\\(.|\n))*\"   {
92                loc_update(yylloc, yytext, yyleng);
93                yylval->string = unescape(yytext+1, yyleng-2, STR_ESCAPES);
94                return DQUOTED;
95   }
96
97   \/([^\\\/]|\\(.|\n))*\/i {
98                loc_update(yylloc, yytext, yyleng);
99                yylval->regexp.nocase = 1;
100                yylval->regexp.pattern = regexp_literal(yytext+1, yyleng-3);
101                return REGEXP;
102   }
103
104   \/([^\\\/]|\\(.|\n))*\/ {
105                loc_update(yylloc, yytext, yyleng);
106                yylval->regexp.nocase = 0;
107                yylval->regexp.pattern = regexp_literal(yytext+1, yyleng-2);
108                return REGEXP;
109   }
110
111   [|*?+()=:;\.\[\]{}-]    return yytext[0];
112
113   module        return KW_MODULE;
114
115   {LETREC}/{WS} return KW_LET_REC;
116
117   let           return KW_LET;
118   string        return KW_STRING;
119   regexp        return KW_REGEXP;
120   lens          return KW_LENS;
121   in            return KW_IN;
122   autoload      return KW_AUTOLOAD;
123
124   /* tests */
125   test          return KW_TEST;
126   get           return KW_GET;
127   put           return KW_PUT;
128   after         return KW_AFTER;
129
130   {ARROW}       return ARROW;
131
132   {QID}         {
133                    yylval->string = strndup(yytext, yyleng);
134                    return QIDENT;
135                 }
136   {LID}         {
137                    yylval->string = strndup(yytext, yyleng);
138                    return LIDENT;
139                 }
140   {UID}         {
141                    yylval->string = strndup(yytext, yyleng);
142                    return UIDENT;
143                 }
144   \(\*          {
145                    augl_get_extra(yyscanner)->comment_depth = 1;
146                    BEGIN(COMMENT);
147                 }
148   .             {
149     report_error(augl_get_info(yyscanner)->error, AUG_ESYNTAX,
150                  "%s:%d:%d: Unexpected character %c",
151                  augl_get_info(yyscanner)->filename->str,
152                  yylineno, yylloc->first_column, yytext[0]);
153                 }
154
155   <<EOF>>       {
156                   augl_close_lexer(yyscanner);
157                   yyterminate();
158                 }
159
160 }
161
162 <COMMENT>
163 {
164   \(\*          {
165                    augl_get_extra(yyscanner)->comment_depth += 1;
166                 }
167   \*\)          {
168                    augl_get_extra(yyscanner)->comment_depth -= 1;
169                    if (augl_get_extra(yyscanner)->comment_depth == 0)
170                        BEGIN(INITIAL);
171                 }
172   .             /* Skip */;
173   <<EOF>>       {
174                   report_error(augl_get_info(yyscanner)->error, AUG_ESYNTAX,
175                                "%s:%d:%d: Missing *)",
176                                augl_get_info(yyscanner)->filename->str,
177                                yylineno, yylloc->first_column);
178                   augl_close_lexer(yyscanner);
179                   yyterminate();
180                 }
181 }
182 %%
183
184 void augl_close_lexer(yyscan_t *scanner) {
185   FILE *fp = augl_get_in(scanner);
186
187   if (fp != NULL) {
188     fclose(fp);
189     augl_set_in(NULL, scanner);
190   }
191 }
192
193 int augl_init_lexer(struct state *state, yyscan_t *scanner) {
194   FILE *f;
195   struct string *name = state->info->filename;
196
197   f = fopen(name->str, "r");
198   if (f == NULL)
199     return -1;
200
201   if (augl_lex_init(scanner) != 0) {
202     fclose(f);
203     return -1;
204   }
205   augl_set_extra(state, *scanner);
206   augl_set_in(f, *scanner);
207   return 0;
208 }
209
210 struct info *augl_get_info(yyscan_t scanner) {
211   return augl_get_extra(scanner)->info;
212 }