]> granicus.if.org Git - icinga2/blob - lib/config/config_lexer.ll
Refactor #includes (Part 3).
[icinga2] / lib / config / config_lexer.ll
1 %{
2 /******************************************************************************
3  * Icinga 2                                                                   *
4  * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
5  *                                                                            *
6  * This program is free software; you can redistribute it and/or              *
7  * modify it under the terms of the GNU General Public License                *
8  * as published by the Free Software Foundation; either version 2             *
9  * of the License, or (at your option) any later version.                     *
10  *                                                                            *
11  * This program is distributed in the hope that it will be useful,            *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
14  * GNU General Public License for more details.                               *
15  *                                                                            *
16  * You should have received a copy of the GNU General Public License          *
17  * along with this program; if not, write to the Free Software Foundation     *
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
19  ******************************************************************************/
20
21 #include "config/configcompiler.h"
22 #include "config/expression.h"
23 #include "config/typerule.h"
24 #include "config/configcompilercontext.h"
25 #include "config/config_parser.h"
26 #include <sstream>
27
28 using namespace icinga;
29
30 #define YY_EXTRA_TYPE ConfigCompiler *
31 #define YY_USER_ACTION                                  \
32 do {                                                    \
33         yylloc->Path = yyextra->GetPath();              \
34         yylloc->FirstLine = yylineno;                   \
35         yylloc->FirstColumn = yycolumn;                 \
36         yylloc->LastLine = yylineno;                    \
37         yylloc->LastColumn = yycolumn + yyleng - 1;     \
38         yycolumn += yyleng;                             \
39 } while (0);
40
41 #define YY_INPUT(buf, result, max_size)                 \
42 do {                                                    \
43         result = yyextra->ReadInput(buf, max_size);     \
44 } while (0)
45
46 struct lex_buf {
47         char *buf;
48         size_t size;
49 };
50
51 static void lb_init(lex_buf *lb)
52 {
53         lb->buf = NULL;
54         lb->size = 0;
55 }
56
57 static void lb_cleanup(lex_buf *lb)
58 {
59         free(lb->buf);
60 }
61
62 static char *lb_steal(lex_buf *lb)
63 {
64         char *buf = lb->buf;
65         lb->buf = NULL;
66         lb->size = 0;
67         return buf;
68 }
69
70 static void lb_append_char(lex_buf *lb, char new_char)
71 {
72         /* round up new_len to the next multiple of 1024 */
73         size_t new_len = ((lb->size + 1) / 1024 + 1) * 1024;
74
75         char *new_buf = (char *)realloc(lb->buf, new_len);
76
77         if (new_buf == NULL && new_len > 0)
78                 throw std::bad_alloc();
79
80         lb->buf = new_buf;
81         lb->size++;
82
83         lb->buf[lb->size - 1] = new_char;
84 }
85 %}
86
87 %option reentrant noyywrap yylineno
88 %option bison-bridge bison-locations
89 %option never-interactive nounistd
90
91 %x C_COMMENT
92 %x STRING
93 %x HEREDOC
94
95 %%
96         lex_buf string_buf;
97
98 \"                              { lb_init(&string_buf); BEGIN(STRING); }
99
100 <STRING>\"                      {
101         BEGIN(INITIAL);
102
103         lb_append_char(&string_buf, '\0');
104
105         yylval->text = lb_steal(&string_buf);
106
107         return T_STRING;
108                                 }
109
110 <STRING>\n                      {
111         std::ostringstream msgbuf;
112         msgbuf << "Unterminated string found: " << *yylloc;
113         ConfigCompilerContext::GetContext()->AddError(false, msgbuf.str());
114         BEGIN(INITIAL);
115                                 }
116
117 <STRING>\\[0-7]{1,3}            {
118         /* octal escape sequence */
119         int result;
120
121         (void) sscanf(yytext + 1, "%o", &result);
122
123         if (result > 0xff) {
124                 /* error, constant is out-of-bounds */
125                 std::ostringstream msgbuf;
126                 msgbuf << "Constant is out-of-bounds: " << yytext << " " << *yylloc;
127                 ConfigCompilerContext::GetContext()->AddError(false, msgbuf.str());
128         }
129
130         lb_append_char(&string_buf, result);
131                                 }
132
133 <STRING>\\[0-9]+                {
134         /* generate error - bad escape sequence; something
135          * like '\48' or '\0777777'
136          */
137         std::ostringstream msgbuf;
138         msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
139         ConfigCompilerContext::GetContext()->AddError(false, msgbuf.str());
140                                 }
141
142 <STRING>\\n                     { lb_append_char(&string_buf, '\n'); }
143 <STRING>\\t                     { lb_append_char(&string_buf, '\t'); }
144 <STRING>\\r                     { lb_append_char(&string_buf, '\r'); }
145 <STRING>\\b                     { lb_append_char(&string_buf, '\b'); }
146 <STRING>\\f                     { lb_append_char(&string_buf, '\f'); }
147 <STRING>\\(.|\n)                { lb_append_char(&string_buf, yytext[1]); }
148
149 <STRING>[^\\\n\"]+              {
150         char *yptr = yytext;
151
152         while (*yptr)
153                 lb_append_char(&string_buf, *yptr++);
154                                }
155
156 \{\{\{                          { lb_init(&string_buf); BEGIN(HEREDOC); }
157
158 <HEREDOC>\}\}\}                 {
159         BEGIN(INITIAL);
160
161         lb_append_char(&string_buf, '\0');
162
163         yylval->text = lb_steal(&string_buf);
164
165         return T_STRING;
166                                 }
167
168 <HEREDOC>(.|\n)                 { lb_append_char(&string_buf, yytext[0]); }
169
170 <INITIAL>{
171 "/*"                            BEGIN(C_COMMENT);
172 }
173
174 <C_COMMENT>{
175 "*/"                            BEGIN(INITIAL);
176 [^*]+                           /* ignore comment */
177 "*"                             /* ignore star */
178 }
179
180 \/\/[^\n]*                      /* ignore C++-style comments */
181 [ \t\r\n]+                      /* ignore whitespace */
182
183 <INITIAL>{
184 type                            return T_TYPE;
185 dictionary                      { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; }
186 array                           { yylval->type = TypeArray; return T_TYPE_ARRAY; }
187 number                          { yylval->type = TypeNumber; return T_TYPE_NUMBER; }
188 string                          { yylval->type = TypeString; return T_TYPE_STRING; }
189 scalar                          { yylval->type = TypeScalar; return T_TYPE_SCALAR; }
190 any                             { yylval->type = TypeAny; return T_TYPE_ANY; }
191 %validator                      { return T_VALIDATOR; }
192 %require                        { return T_REQUIRE; }
193 %attribute                      { return T_ATTRIBUTE; }
194 abstract                        return T_ABSTRACT;
195 local                           return T_LOCAL;
196 object                          return T_OBJECT;
197 template                        return T_TEMPLATE;
198 #include                        return T_INCLUDE;
199 #library                        return T_LIBRARY;
200 inherits                        return T_INHERITS;
201 null                            return T_NULL;
202 partial                         return T_PARTIAL;
203 true                            { yylval->num = 1; return T_NUMBER; }
204 false                           { yylval->num = 0; return T_NUMBER; }
205 [a-zA-Z_\*][:a-zA-Z0-9\-_\*]*   { yylval->text = strdup(yytext); return T_IDENTIFIER; }
206 \<[^\>]*\>                      { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; }
207 -?[0-9]+(\.[0-9]+)?ms           { yylval->num = strtod(yytext, NULL) / 1000; return T_NUMBER; }
208 -?[0-9]+(\.[0-9]+)?h            { yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; }
209 -?[0-9]+(\.[0-9]+)?m            { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; }
210 -?[0-9]+(\.[0-9]+)?s            { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
211 -?[0-9]+(\.[0-9]+)?             { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
212 =                               { yylval->op = OperatorSet; return T_EQUAL; }
213 \+=                             { yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
214 -=                              { yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
215 \*=                             { yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }
216 \/=                             { yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; }
217 }
218
219 .                               return yytext[0];
220
221 %%
222
223 void ConfigCompiler::InitializeScanner(void)
224 {
225         yylex_init(&m_Scanner);
226         yyset_extra(this, m_Scanner);
227 }
228
229 void ConfigCompiler::DestroyScanner(void)
230 {
231         yylex_destroy(m_Scanner);
232 }