Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | ******************************************************************************/ | |
8 | %option noyywrap | |
9 | %option never-interactive | |
10 | %option nounput | |
11 | %option stack | |
12 | %option noyy_top_state | |
13 | %option prefix="coding_attrib_" | |
14 | ||
15 | %{ | |
16 | ||
17 | /* Lexer for "extension" attributes of functions, external functions and | |
18 | * port types related to message encoding. */ | |
19 | ||
20 | #include <ctype.h> | |
21 | ||
22 | #include "../string.hh" | |
23 | #include "../Identifier.hh" | |
24 | #include "Attributes.hh" | |
25 | #include "Ttcnstuff.hh" | |
26 | ||
27 | using namespace Ttcn; | |
28 | using namespace Common; | |
29 | ||
30 | #include "coding_attrib_p.hh" | |
31 | ||
32 | #define yylval coding_attrib_lval | |
33 | #define yylloc coding_attrib_lloc | |
34 | ||
35 | /** global variable indicating the location of the returned token to bison */ | |
36 | extern YYLTYPE yylloc; | |
37 | ||
38 | /** the name of the current input file */ | |
39 | const char *coding_attrib_infile; | |
40 | ||
41 | /** always points to the first character of the regexp to be recognized */ | |
42 | static int current_line, current_column; | |
43 | ||
44 | /** the actual size of state condition stack */ | |
45 | static size_t stack_size = 0; | |
46 | ||
47 | static void fill_location() | |
48 | { | |
49 | yylloc.first_line = current_line; | |
50 | yylloc.first_column = current_column; | |
51 | current_column += yyleng; | |
52 | yylloc.last_line = current_line; | |
53 | yylloc.last_column = current_column; | |
54 | } | |
55 | ||
56 | #define PUSH_STATE(new_state) yy_push_state(new_state); stack_size++ | |
57 | ||
58 | #define RETURN(ret_val) fill_location(); last_token = ret_val; return ret_val | |
59 | ||
60 | %} | |
61 | ||
62 | LINECOMMENT "//"[^\r\n]* | |
63 | WHITESPACE [ \t\v\f] | |
64 | NEWLINE \r|\n|\r\n | |
65 | IDENTIFIER [A-Za-z][A-Za-z0-9_]* | |
66 | NUMBER 0|[1-9][0-9]* | |
67 | ||
68 | %s SC_start | |
69 | %s SC_prototype SC_errorbehavior | |
70 | %s SC_encodingtype SC_encodingoptions | |
71 | %s SC_user SC_typemappinglist SC_mappingtype SC_functionmapping | |
72 | %s SC_printing | |
73 | ||
74 | %x SC_blockcomment | |
75 | ||
76 | %% | |
77 | /* local variables of yylex() */ | |
78 | static int last_token = EOF; | |
79 | int start_line = 0, start_column = 0; /**< used by block comments */ | |
80 | ||
81 | /* eat up whitespaces and line comments in all states */ | |
82 | ||
83 | <*>{ | |
84 | {WHITESPACE}+|{LINECOMMENT} current_column += yyleng; | |
85 | {WHITESPACE}*{NEWLINE} { | |
86 | current_line++; | |
87 | current_column = 0; | |
88 | } | |
89 | } | |
90 | ||
91 | "/*" { | |
92 | start_line = current_line; | |
93 | start_column = current_column; | |
94 | current_column += yyleng; | |
95 | PUSH_STATE(SC_blockcomment); | |
96 | } | |
97 | ||
98 | <SC_blockcomment>{ | |
99 | "*/" { | |
100 | current_column += yyleng; | |
101 | yy_pop_state(); | |
102 | stack_size--; | |
103 | } | |
104 | [^\r\n] current_column++; | |
105 | } | |
106 | ||
107 | <SC_errorbehavior>{IDENTIFIER} { | |
108 | yylval.str = new string(yyleng, yytext); | |
109 | RETURN(ErrorBehaviorString); | |
110 | } | |
111 | ||
112 | <SC_encodingoptions>[^ \t\r\n\(\)]+ { | |
113 | yylval.str = new string(yyleng, yytext); | |
114 | RETURN(EncodingOption); | |
115 | } | |
116 | ||
117 | <SC_printing>{ | |
118 | compact RETURN(CompactKeyword); | |
119 | pretty RETURN(PrettyKeyword); | |
120 | } | |
121 | ||
122 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
123 | * Initial start condition. Will switch to another start condition later, | |
124 | * when the opening paren '(' is encountered. | |
125 | */ | |
126 | <SC_start>{ | |
127 | prototype RETURN(PrototypeKeyword); | |
128 | ||
129 | address RETURN(AddressKeyword); | |
130 | /* porttype */ | |
131 | internal RETURN(InternalKeyword); | |
132 | provider RETURN(ProviderKeyword); | |
133 | user { | |
134 | BEGIN(SC_user); | |
135 | RETURN(UserKeyword); | |
136 | } | |
137 | anytype RETURN(AnyTypeKeyword); | |
138 | ||
139 | version RETURN(VersionKeyword); | |
140 | requires RETURN(RequiresKeyword); | |
141 | requiresTITAN RETURN(ReqTitanKeyword); | |
142 | ||
143 | transparent RETURN(TransparentKeyword); | |
144 | } | |
145 | ||
146 | /* TTCN-3 keywords are valid in all (non-exclusive) states */ | |
147 | ||
148 | bitstring RETURN(BitStringKeyword); | |
149 | boolean RETURN(BooleanKeyword); | |
150 | charstring RETURN(CharStringKeyword); | |
151 | default RETURN(DefaultKeyword); | |
152 | float RETURN(FloatKeyword); | |
153 | function RETURN(FunctionKeyword); | |
154 | hexstring RETURN(HexStringKeyword); | |
155 | in RETURN(InKeyword); | |
156 | integer RETURN(IntegerKeyword); | |
157 | objid RETURN(ObjectIdentifierKeyword); | |
158 | octetstring RETURN(OctetStringKeyword); | |
159 | out RETURN(OutKeyword); | |
160 | universal RETURN(UniversalKeyword); | |
161 | verdicttype RETURN(VerdictTypeKeyword); | |
162 | ||
163 | /* the rest of the keywords are context sensitive */ | |
164 | ||
165 | <SC_start,SC_mappingtype>{ | |
166 | decode RETURN(DecodeKeyword); | |
167 | encode RETURN(EncodeKeyword); | |
168 | errorbehavior RETURN(ErrorBehaviorKeyword); | |
169 | printing RETURN(PrintingKeyword); | |
170 | } | |
171 | ||
172 | <SC_mappingtype>{ | |
173 | discard RETURN(DiscardKeyword); | |
174 | simple RETURN(SimpleKeyword); | |
175 | } | |
176 | ||
177 | <SC_prototype>{ | |
178 | backtrack { | |
179 | yylval.prototype = Def_Function_Base::PROTOTYPE_BACKTRACK; | |
180 | RETURN(PrototypeSetting); | |
181 | } | |
182 | convert { | |
183 | yylval.prototype = Def_Function_Base::PROTOTYPE_CONVERT; | |
184 | RETURN(PrototypeSetting); | |
185 | } | |
186 | fast { | |
187 | yylval.prototype = Def_Function_Base::PROTOTYPE_FAST; | |
188 | RETURN(PrototypeSetting); | |
189 | } | |
190 | sliding { | |
191 | yylval.prototype = Def_Function_Base::PROTOTYPE_SLIDING; | |
192 | RETURN(PrototypeSetting); | |
193 | } | |
194 | } | |
195 | ||
196 | <SC_encodingtype>{ | |
197 | BER { | |
198 | yylval.encoding_type = Type::CT_BER; | |
199 | RETURN(EncodingType); | |
200 | } | |
201 | PER { | |
202 | yylval.encoding_type = Type::CT_PER; | |
203 | RETURN(EncodingType); | |
204 | } | |
205 | XER { | |
206 | yylval.encoding_type = Type::CT_XER; | |
207 | RETURN(EncodingType); | |
208 | } | |
209 | RAW { | |
210 | yylval.encoding_type = Type::CT_RAW; | |
211 | RETURN(EncodingType); | |
212 | } | |
213 | TEXT { | |
214 | yylval.encoding_type = Type::CT_TEXT; | |
215 | RETURN(EncodingType); | |
216 | } | |
217 | JSON { | |
218 | yylval.encoding_type = Type::CT_JSON; | |
219 | RETURN(EncodingType); | |
220 | } | |
221 | } | |
222 | ||
223 | {IDENTIFIER} { | |
224 | yylval.id = new Identifier(Identifier::ID_TTCN, string(yyleng, yytext)); | |
225 | RETURN(IDentifier); | |
226 | } | |
227 | ||
228 | {NUMBER} { | |
229 | yylval.number = atoi(yytext); | |
230 | RETURN(Number); | |
231 | } | |
232 | ||
233 | ||
234 | "->" RETURN(RedirectSymbol); | |
235 | ||
236 | \( { | |
237 | switch (last_token) { | |
238 | case PrototypeKeyword: | |
239 | PUSH_STATE(SC_prototype); | |
240 | break; | |
241 | case EncodeKeyword: | |
242 | case DecodeKeyword: | |
243 | PUSH_STATE(SC_encodingtype); | |
244 | break; | |
245 | case ErrorBehaviorKeyword: | |
246 | PUSH_STATE(SC_errorbehavior); | |
247 | break; | |
248 | case InKeyword: | |
249 | case OutKeyword: | |
250 | PUSH_STATE(SC_typemappinglist); | |
251 | break; | |
252 | case FunctionKeyword: | |
253 | PUSH_STATE(SC_functionmapping); | |
254 | break; | |
255 | case PrintingKeyword: | |
256 | PUSH_STATE(SC_printing); | |
257 | break; | |
258 | default: | |
259 | PUSH_STATE(YY_START); /* Push the current state (duplicate) */ | |
260 | break; | |
261 | } | |
262 | if (YY_START == SC_encodingoptions) { | |
263 | yylval.str = new string(yyleng, yytext); | |
264 | RETURN(EncodingOption); | |
265 | } else { | |
266 | RETURN('('); | |
267 | } | |
268 | } | |
269 | ||
270 | \) { | |
271 | if (stack_size > 0) { | |
272 | yy_pop_state(); | |
273 | stack_size--; | |
274 | } | |
275 | if (YY_START == SC_encodingoptions) { | |
276 | yylval.str = new string(yyleng, yytext); | |
277 | RETURN(EncodingOption); | |
278 | } else { | |
279 | if (YY_START == SC_user) BEGIN(SC_start); | |
280 | RETURN(')'); | |
281 | } | |
282 | } | |
283 | ||
284 | : { | |
285 | switch (YY_START) /* current start condition is... */ { | |
286 | case SC_encodingtype: /* BER | RAW | ... */ | |
287 | BEGIN(SC_encodingoptions); | |
288 | break; | |
289 | case SC_typemappinglist: | |
290 | BEGIN(SC_mappingtype); | |
291 | break; | |
292 | } | |
293 | RETURN(':'); | |
294 | } | |
295 | ||
296 | \,|\; { | |
297 | if (YY_START == SC_mappingtype) BEGIN(SC_typemappinglist); | |
298 | RETURN(*yytext); | |
299 | } | |
300 | ||
301 | [-.<>/] RETURN(*yytext); | |
302 | ||
303 | <*>{ | |
304 | . { | |
305 | fill_location(); | |
306 | Location loc(coding_attrib_infile, yylloc); | |
307 | int c = (unsigned char)yytext[0]; | |
308 | loc.error("Character `%c' (0x%02X) cannot be used in extension attribute", | |
309 | isprint(c) ? c : '?', c); | |
310 | } | |
311 | <<EOF>> { | |
312 | if (YY_START == SC_blockcomment) { | |
313 | Location loc(coding_attrib_infile, start_line, start_column, | |
314 | current_line, current_column); | |
315 | loc.error("Unterminated block comment"); | |
316 | } | |
317 | /* we must set the fake length 1 in order to report the single column number | |
318 | * of the unexpected EOF in error messages */ | |
319 | yyleng = 1; | |
320 | RETURN(EOF); | |
321 | } | |
322 | } | |
323 | ||
324 | %% | |
325 | ||
326 | void init_coding_attrib_lex(/*char definition_type,*/ const AttributeSpec& attrib) | |
327 | { | |
328 | if (stack_size > 0) | |
329 | FATAL_ERROR("init_coding_attrib_lex(): stack is not empty"); | |
330 | coding_attrib_infile = attrib.get_filename(); | |
331 | current_line = attrib.get_first_line(); | |
332 | /* skip the leading " of the attribute value */ | |
333 | current_column = attrib.get_first_column() + 1; | |
334 | const string& s = attrib.get_spec(); | |
335 | yy_scan_bytes(s.c_str(), s.size()); | |
336 | BEGIN(SC_start); | |
337 | } | |
338 | ||
339 | void cleanup_coding_attrib_lex() | |
340 | { | |
341 | while (stack_size > 0) { | |
342 | yy_pop_state(); | |
343 | stack_size--; | |
344 | } | |
345 | coding_attrib_lex_destroy(); | |
346 | } |