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