diff options
Diffstat (limited to 'src/belex.l')
-rw-r--r-- | src/belex.l | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/belex.l b/src/belex.l new file mode 100644 index 0000000..f35f114 --- /dev/null +++ b/src/belex.l | |||
@@ -0,0 +1,178 @@ | |||
1 | %option nounput | ||
2 | %option noinput | ||
3 | |||
4 | %{ | ||
5 | #include "backend.h" | ||
6 | |||
7 | enum { | ||
8 | T_BOGUS = 256, | ||
9 | T_IDENT, | ||
10 | T_NUMBER, | ||
11 | T_STRING, | ||
12 | T_BACKEND, | ||
13 | T_HOST, | ||
14 | T_PORT | ||
15 | }; | ||
16 | |||
17 | static char const *input_string; | ||
18 | static size_t input_len; | ||
19 | static size_t input_pos; | ||
20 | static char const *string_start; | ||
21 | static size_t current_pos; | ||
22 | |||
23 | #define YY_INPUT(buf,result,max_size) \ | ||
24 | do { \ | ||
25 | size_t n = input_len - input_pos; \ | ||
26 | if (n > max_size) \ | ||
27 | n = max_size; \ | ||
28 | memcpy(buf, input_string, n); \ | ||
29 | input_pos += n; \ | ||
30 | result = n; \ | ||
31 | } while (0) | ||
32 | |||
33 | #define YY_USER_ACTION \ | ||
34 | current_pos += yyleng; | ||
35 | |||
36 | #define YY_DECL static int yylex(void) | ||
37 | static int yywrap(void); | ||
38 | |||
39 | static char const * | ||
40 | input_point(void) | ||
41 | { | ||
42 | return input_string + current_pos; | ||
43 | } | ||
44 | |||
45 | #define YYSTYPE be_string_t | ||
46 | #define YYSTYPE_INITIALIZER { NULL, 0 } | ||
47 | |||
48 | static YYSTYPE yylval; | ||
49 | %} | ||
50 | |||
51 | %x COMMENT STR | ||
52 | |||
53 | %% | ||
54 | /* C-style comments */ | ||
55 | "/*" BEGIN(COMMENT); | ||
56 | <COMMENT>[^*]* /* eat anything that's not a '*' */ | ||
57 | <COMMENT>"*"+[^*/]* /* eat up '*'s not followed by '/'s */ | ||
58 | <COMMENT>"*"+"/" BEGIN(INITIAL); | ||
59 | |||
60 | /* Single-line comments */ | ||
61 | "//".*\n ; | ||
62 | #.*\n ; | ||
63 | |||
64 | /* Multi-line strings */ | ||
65 | "{\"" { BEGIN(STR); string_start = input_point(); } | ||
66 | <STR>[^\"]* /* eat anything that's not a '"' */ | ||
67 | <STR>"\""+[^"}]* /* eat up '"'s not followed by '}'s */ | ||
68 | <STR>"\""+"}" { BEGIN(INITIAL); | ||
69 | yylval.start = string_start; | ||
70 | yylval.len = input_point() - yylval.start - 2; | ||
71 | return T_STRING; | ||
72 | } | ||
73 | /* Single-line strings */ | ||
74 | \".*\" { | ||
75 | yylval.start = input_point() - yyleng + 1; | ||
76 | yylval.len = yyleng - 2; | ||
77 | return T_STRING; | ||
78 | } | ||
79 | backend return T_BACKEND; | ||
80 | ".host" return T_HOST; | ||
81 | ".port" return T_PORT; | ||
82 | "{"|"}"|"="|";" return yytext[0]; | ||
83 | |||
84 | [a-zA-Z_][a-zA-Z0-9_.]+ { | ||
85 | yylval.start = input_point() - yyleng; | ||
86 | yylval.len = yyleng; | ||
87 | return T_IDENT; | ||
88 | } | ||
89 | [0-9]+ return T_NUMBER; | ||
90 | |||
91 | [ \t\n]+ ; | ||
92 | |||
93 | . return T_BOGUS; | ||
94 | |||
95 | %% | ||
96 | int | ||
97 | yywrap(void) | ||
98 | { | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | set_input(char const *str, size_t len) | ||
104 | { | ||
105 | input_string = str; | ||
106 | input_len = len; | ||
107 | input_pos = 0; | ||
108 | current_pos = 0; | ||
109 | } | ||
110 | |||
111 | static int brace_nesting; | ||
112 | |||
113 | static void | ||
114 | read_backend(regfun_t regfun, void *d) | ||
115 | { | ||
116 | int c; | ||
117 | int in_statement; | ||
118 | YYSTYPE label, host = YYSTYPE_INITIALIZER, port = YYSTYPE_INITIALIZER; | ||
119 | |||
120 | if ((c = yylex()) != T_IDENT && c != T_STRING) | ||
121 | return; | ||
122 | label = yylval; | ||
123 | if ((c = yylex()) != '{') | ||
124 | return; | ||
125 | brace_nesting++; | ||
126 | in_statement = 0; | ||
127 | while (brace_nesting == 1) { | ||
128 | c = yylex(); | ||
129 | if (c == 0) | ||
130 | break; | ||
131 | else if (c == '{') | ||
132 | brace_nesting++; | ||
133 | else if (c == '}') | ||
134 | brace_nesting++; | ||
135 | else if (in_statement) { | ||
136 | if (c == ';') | ||
137 | in_statement = 0; | ||
138 | } else { | ||
139 | in_statement = 1; | ||
140 | if (c == T_HOST || c == T_PORT) { | ||
141 | YYSTYPE *stk = c == T_HOST ? &host : &port; | ||
142 | in_statement = 1; | ||
143 | if ((c = yylex()) == '=') { | ||
144 | c = yylex(); | ||
145 | if (c == T_STRING || c == T_IDENT) { | ||
146 | *stk = yylval; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | regfun(&label, &host, &port, d); | ||
153 | } | ||
154 | |||
155 | void | ||
156 | backend_parser(const char *str, size_t len, regfun_t regfun, void *d) | ||
157 | { | ||
158 | int c; | ||
159 | |||
160 | set_input(str, len); | ||
161 | |||
162 | brace_nesting = 0; | ||
163 | while ((c = yylex())) { | ||
164 | if (brace_nesting == 0) { | ||
165 | if (c == T_BACKEND) { | ||
166 | read_backend(regfun, d); | ||
167 | } | ||
168 | } | ||
169 | switch (c) { | ||
170 | case '{': | ||
171 | brace_nesting++; | ||
172 | break; | ||
173 | case '}': | ||
174 | brace_nesting--; | ||
175 | break; | ||
176 | } | ||
177 | } | ||
178 | } | ||