Commit | Line | Data |
---|---|---|
970ed795 | 1 | /****************************************************************************** |
3abe9331 | 2 | * Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
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 | ||
12 | %{ | |
13 | ||
14 | #include "../../common/memory.h" | |
15 | #include "../Int.hh" | |
16 | #include "../Real.hh" | |
17 | #include "../Setting.hh" | |
18 | #include "../Value.hh" | |
19 | #include "../main.hh" | |
20 | #include "RawAST.hh" | |
21 | #include "../XerAttributes.hh" | |
22 | #include "rawASTspec.h" | |
23 | // the next one is the header generated from the .y | |
24 | #include "rawAST.tab.hh" | |
25 | #include "AST_ttcn3.hh" | |
26 | #include "Attributes.hh" | |
27 | #include "BerAST.hh" | |
28 | ||
29 | using namespace Common; | |
30 | ||
31 | #define ALLOCATE_IF_NULL(retv, oldptr, ptype) \ | |
32 | if((oldptr)==NULL){\ | |
33 | retv = (ptype*)Malloc(sizeof(ptype)); \ | |
34 | } else \ | |
35 | retv = oldptr; | |
36 | ||
37 | const Common::Module *mymod; | |
38 | RawAST *rawstruct; | |
39 | TextAST *textstruct; | |
40 | XerAttributes *xerstruct; | |
41 | BerAST *berstruct; | |
42 | JsonAST *jsonstruct; | |
43 | bool raw_f; | |
44 | bool text_f; | |
45 | bool xer_f; | |
46 | bool ber_f; | |
47 | bool json_f; | |
48 | int length_multiplier; | |
49 | ||
50 | extern void rawAST_error(const char *str); /* defined in this file */ | |
51 | extern int rawAST_parse(); /* in rawAST.tab.cc, generated from rawAST.y */ | |
52 | ||
53 | //rawAST_full_spec rawAST_result; | |
54 | //rawAST_encoding_spec rawAST_partial_result; | |
55 | ||
56 | extern int rawAST_debug; | |
57 | ||
58 | #define yylval rawAST_lval | |
59 | #define yylloc rawAST_lloc | |
60 | ||
61 | extern YYLTYPE yylloc; | |
62 | ||
63 | /* always points to the first character of the regexp to be recognized */ | |
64 | static int current_line, current_column; | |
65 | ||
66 | static void update_lloc() | |
67 | { | |
68 | yylloc.first_line = current_line; | |
69 | yylloc.first_column = current_column; | |
70 | current_column += yyleng; | |
71 | yylloc.last_line = current_line; | |
72 | yylloc.last_column = current_column; | |
73 | } | |
74 | ||
75 | #define RETURN(retv) update_lloc(); return retv | |
76 | ||
77 | %} | |
78 | ||
79 | /* definitions */ | |
80 | ||
81 | LINECOMMENT "//"[^\r\n]* | |
82 | WHITESPACE [ \t\v\f]+ | |
83 | NEWLINE \r|\n|\r\n | |
84 | ||
85 | BIN 0|1 | |
86 | HEX [0-9A-Fa-f] | |
87 | OCT {HEX}{HEX} | |
88 | FLOAT ({NUMBER}\.[0-9]+)|((({NUMBER}(\.[0-9]+)?)|(\.[0-9]+))[Ee][+-]?{NUMBER}) | |
89 | NUMBER 0|([1-9][0-9]*) | |
90 | IDENTIFIER [A-Za-z][A-Za-z0-9_]* | |
91 | DQUOTE (\"|\\)\" | |
92 | CHAR [^\"\\]|\\[^\"]|{DQUOTE}{DQUOTE} | |
93 | MATCH_CHAR [^'\\]|"''"|\\(.|\n) | |
94 | RPAREN [)] | |
95 | ||
96 | /* start conditions (x: exclusive) */ | |
97 | ||
98 | %x ccomment | |
99 | %x textcodec | |
100 | %x rawcodec | |
101 | %x jsoncodec | |
102 | %x jsonvalue | |
103 | ||
104 | %% | |
105 | int comment_caller = INITIAL; | |
106 | ||
107 | <INITIAL,textcodec,rawcodec>{ /* all but ccomment */ | |
108 | "/*" { | |
109 | yylloc.first_line = current_line; | |
110 | yylloc.first_column = current_column; | |
111 | current_column += yyleng; | |
112 | comment_caller = YY_START; | |
113 | BEGIN(ccomment); | |
114 | } | |
115 | ||
116 | {WHITESPACE}|{LINECOMMENT} current_column += yyleng; | |
117 | ||
118 | } /* end <all but ccomment> */ | |
119 | ||
120 | <*>{NEWLINE} current_line++; current_column = 0; | |
121 | ||
122 | <ccomment>{ | |
123 | "*/" current_column += yyleng; BEGIN(comment_caller); | |
124 | . current_column++; | |
125 | <<EOF>> { | |
126 | yylloc.last_line = current_line; | |
127 | yylloc.last_column = current_column; | |
128 | Location loc(infile, yylloc); | |
129 | loc.error("Unterminated block comment in variant attribute"); | |
130 | RETURN(EOF); | |
131 | } | |
132 | } /* ccomment end */ | |
133 | ||
134 | <INITIAL,textcodec,rawcodec>{NUMBER} { | |
135 | update_lloc(); | |
136 | Location loc(infile, yylloc); | |
137 | yylval.intval = string2Int(yytext, loc); | |
138 | return XNumber; | |
139 | } | |
140 | ||
141 | <rawcodec,INITIAL>{ | |
142 | ||
143 | {FLOAT} { | |
144 | update_lloc(); | |
145 | Location loc(infile, yylloc); | |
146 | yylval.floatval = string2Real(yytext, loc); | |
147 | return XFloatValue; | |
148 | } | |
149 | true { yylval.boolval = true; | |
150 | RETURN(XBooleanConst);} | |
151 | false { yylval.boolval = false; | |
152 | RETURN(XBooleanConst);} | |
153 | none { yylval.verdictval = Value::Verdict_NONE; | |
154 | RETURN(XVerdictConst);} | |
155 | pass { yylval.verdictval = Value::Verdict_PASS; | |
156 | RETURN(XVerdictConst);} | |
157 | inconc { yylval.verdictval = Value::Verdict_INCONC; | |
158 | RETURN(XVerdictConst);} | |
159 | fail { yylval.verdictval = Value::Verdict_FAIL; | |
160 | RETURN(XVerdictConst);} | |
161 | error { yylval.verdictval = Value::Verdict_ERROR; | |
162 | RETURN(XVerdictConst);} | |
163 | null RETURN(XNullKeyword); | |
164 | NULL RETURN(XNULLKeyword); | |
165 | omit RETURN(XOmitKeyword); | |
166 | ||
167 | {DQUOTE}{CHAR}*{DQUOTE} { | |
168 | yylloc.first_line = current_line; | |
169 | /* we have to cheat because parse_charstring_value() expects one quotation | |
170 | * mark character as delimiter, but {DQUOTE} matches two characters */ | |
171 | yylloc.first_column = current_column + 1; | |
172 | current_column += 2; | |
173 | bool backslash_flag = false; | |
174 | yylval.str = memptystr(); | |
3abe9331 | 175 | for (size_t i = 2; i < yyleng - 2; ) { |
970ed795 EL |
176 | if (!backslash_flag && (yytext[i] == '\\' || yytext[i] == '"') && |
177 | yytext[i + 1] == '"' && | |
178 | (yytext[i + 2] == '\\' || yytext[i + 2] == '"') && | |
179 | yytext[i + 3] == '"') { | |
180 | /* transform embedded escaped quotes: \"\" or """" -> "" */ | |
181 | /* we must use the octal notation to keep the column numbers in synch */ | |
182 | yylval.str = mputstr(yylval.str, "\\042"); | |
183 | current_column += 4; | |
184 | i += 4; | |
185 | } else if (yytext[i] == '\r' && yytext[i + 1] == '\n') { | |
186 | /* handle the CR-LF sequence as a single newline */ | |
187 | yylval.str = mputstr(yylval.str, "\r\n"); | |
188 | current_line++; | |
189 | current_column = 0; | |
190 | backslash_flag = false; | |
191 | i += 2; | |
192 | } else { | |
193 | yylval.str = mputc(yylval.str, yytext[i]); | |
194 | if (yytext[i] == '\r' || yytext[i] == '\n') { | |
195 | current_line++; | |
196 | current_column = 0; | |
197 | } else current_column++; | |
198 | if (backslash_flag) backslash_flag = false; | |
199 | else if (yytext[i] == '\\') backslash_flag = true; | |
200 | i++; | |
201 | } | |
202 | } | |
203 | current_column += 2; | |
204 | yylloc.last_line = current_line; | |
205 | yylloc.last_column = current_column - 1; | |
206 | return XCstring; | |
207 | } | |
208 | ||
209 | '{BIN}*'B { | |
210 | yytext[yyleng - 2] = '\0'; | |
211 | yylval.str = mcopystr(yytext + 1); | |
212 | RETURN(XBstring); | |
213 | } | |
214 | ||
215 | '[^\']*'B { /* a properly delimited bit string with incorrect content */ | |
216 | /* the backslash in the character class is redundant, but helps editors | |
217 | * get the syntax highlighting right */ | |
218 | update_lloc(); | |
219 | rawAST_error("invalid bitstring value"); | |
220 | yylval.str = memptystr(); | |
221 | return XBstring; | |
222 | } | |
223 | ||
224 | '{HEX}*'H { | |
225 | yytext[yyleng - 2] = '\0'; | |
226 | yylval.str = mcopystr(yytext + 1); | |
227 | RETURN(XHstring); | |
228 | } | |
229 | ||
230 | '[^\']*'H { /* a properly delimited hex string with incorrect content */ | |
231 | update_lloc(); | |
232 | rawAST_error("invalid hexstring value"); | |
233 | yylval.str = memptystr(); | |
234 | return XHstring; | |
235 | } | |
236 | ||
237 | '{OCT}*'O { | |
238 | yytext[yyleng - 2] = '\0'; | |
239 | yylval.str = mcopystr(yytext + 1); | |
240 | RETURN(XOstring); | |
241 | } | |
242 | ||
243 | '[^\']*'O { /* a properly delimited octet string with incorrect content */ | |
244 | update_lloc(); | |
245 | rawAST_error("invalid octetstring value"); | |
246 | yylval.str = memptystr(); | |
247 | return XOstring; | |
248 | } | |
249 | ||
250 | ||
251 | '[^\']*' { /* A string delimited by a pair of ' */ | |
252 | yytext[yyleng - 1] = '\0'; | |
253 | yylval.str = mcopystr(yytext + 1); | |
254 | RETURN(Xstring); | |
255 | } | |
256 | ||
257 | } /* end <rawcodec,INITIAL> */ | |
258 | ||
259 | /* RAW encoder keywords */ | |
260 | PADDING { BEGIN(rawcodec); RETURN(XPaddingKeyword); } | |
261 | PREPADDING { BEGIN(rawcodec); RETURN(XPrePaddingKeyword); } | |
262 | PADDING_PATTERN { BEGIN(rawcodec); RETURN(XPaddingPatternKeyword); } | |
263 | PADDALL RETURN(XPaddAllKeyword); | |
264 | FIELDORDER { BEGIN(rawcodec); RETURN(XFieldOrderKeyword); } | |
265 | EXTENSION_BIT { BEGIN(rawcodec); RETURN(XExtensionBitKeyword); } | |
266 | EXTENSION_BIT_GROUP { BEGIN(rawcodec); RETURN(XExtensionBitGroupKeyword); } | |
267 | LENGTHTO { BEGIN(rawcodec); RETURN(XLengthToKeyword); } | |
268 | POINTERTO { BEGIN(rawcodec); RETURN(XPointerToKeyword); } | |
269 | UNIT { BEGIN(rawcodec); RETURN(XUnitKeyword); } | |
270 | PTRUNIT { BEGIN(rawcodec); RETURN(XPtrUnitKeyword); } | |
271 | REPEATABLE { BEGIN(rawcodec); RETURN(XRepeatableKeyword); } | |
272 | PTROFFSET { BEGIN(rawcodec); RETURN(XPtrOffsetKeyword); } | |
273 | LENGTHINDEX { BEGIN(rawcodec); RETURN(XLengthIndexKeyword); } | |
274 | TAG { BEGIN(rawcodec); RETURN(XTagKeyword); } | |
275 | CROSSTAG { BEGIN(rawcodec); RETURN(XCrossTagKeyword); } | |
276 | PRESENCE { BEGIN(rawcodec); RETURN(XPresenceKeyword); } | |
277 | FIELDLENGTH { BEGIN(rawcodec); RETURN(XFieldLengthKeyword); } | |
278 | FORMAT { BEGIN(rawcodec); RETURN(XFieldLengthKeyword); } | |
279 | ALIGN { BEGIN(rawcodec); RETURN(XAlignKeyword); } | |
280 | BYTEORDER { BEGIN(rawcodec); RETURN(XByteOrderKeyword); } | |
281 | COMP { BEGIN(rawcodec); RETURN(XCompKeyword); } | |
282 | BITORDER { BEGIN(rawcodec); RETURN(XBitOrderKeyword); } | |
283 | BITORDERINFIELD { BEGIN(rawcodec); RETURN(XBitOrderInFieldKeyword); } | |
284 | BITORDERINOCTET { BEGIN(rawcodec); RETURN(XBitOrderInOctetKeyword); } | |
285 | HEXORDER { BEGIN(rawcodec); RETURN(XHexOrderKeyword); } | |
286 | TOPLEVEL { BEGIN(rawcodec); RETURN(XToplevelKeyword); } | |
3abe9331 | 287 | IntX { RETURN(XIntXKeyword); } |
51fa56b9 | 288 | bit { RETURN(XBitKeyword); } |
289 | unsigned { RETURN(XUnsignedKeyword); } | |
970ed795 EL |
290 | |
291 | <rawcodec>{ | |
292 | yes { yylval.enumval = XDEFYES; RETURN(XYes); } | |
293 | no { yylval.enumval = XDEFNO; RETURN(XNo); } | |
294 | reverse { yylval.enumval = XDEFREVERSE; RETURN (XReverse); } | |
295 | msb { yylval.enumval = XDEFMSB; RETURN(XMsb); } | |
296 | lsb { yylval.enumval = XDEFLSB; RETURN(XLsb); } | |
297 | bits { yylval.enumval = 1; RETURN(XBits); } | |
298 | bit { yylval.enumval = 1; RETURN(XBits); } | |
299 | octets { yylval.enumval = 8; RETURN(XOctets); } | |
300 | octet { yylval.enumval = 8; RETURN(XOctets); } | |
301 | nibble { yylval.enumval = 4; RETURN(XOctets); } | |
302 | word16 { yylval.enumval = 16; RETURN(XOctets); } | |
303 | dword32 { yylval.enumval = 32; RETURN(XOctets); } | |
304 | elements { yylval.enumval = -1; RETURN(XOctets); } | |
305 | variable { yylval.intval = 0; RETURN(XNumber);} | |
306 | IEEE754[ ]double { yylval.intval = 64; RETURN(XNumber);} | |
307 | IEEE754[ ]float { yylval.intval = 32; RETURN(XNumber);} | |
308 | left { yylval.enumval = XDEFLEFT; RETURN(XLeft); } | |
309 | right { yylval.enumval = XDEFRIGHT; RETURN(XRight); } | |
310 | nosign { yylval.enumval = XDEFUNSIGNED; RETURN(XUnsigned); } | |
311 | 2scompl { yylval.enumval = XDEFCOMPL; RETURN(XCompl); } | |
312 | signbit { yylval.enumval = XDEFSIGNBIT; RETURN(XSignbit); } | |
313 | first { yylval.enumval = XDEFFIRST; RETURN(XFirst); } | |
314 | last { yylval.enumval = XDEFLAST; RETURN(XLast); } | |
315 | low { yylval.enumval = XDEFLOW; RETURN(XLow); } | |
316 | high { yylval.enumval = XDEFHIGH; RETURN(XHigh); } | |
317 | OTHERWISE RETURN(XOtherwise); | |
318 | ||
319 | {RPAREN} {BEGIN(INITIAL);RETURN(*yytext);} | |
320 | ||
321 | } /* end <rawcodec> */ | |
322 | ||
323 | /* TEXT codec starters */ | |
324 | BEGIN { BEGIN(textcodec);RETURN(XBeginKeyword);} | |
325 | END { BEGIN(textcodec);RETURN(XEndKeyword);} | |
326 | SEPARATOR { BEGIN(textcodec);RETURN(XSeparatorKeyword);} | |
327 | TEXT_CODING { BEGIN(textcodec);RETURN(XCodingKeyword); } | |
328 | ||
329 | <INITIAL>{ | |
330 | ||
331 | /* XER attributes are not as well delimited like TEXT/RAW, | |
332 | * so no start condition for them (it would be difficult to determine | |
333 | * when to return to INITIAL) */ | |
334 | ||
335 | /* First, the "starter" attributes */ | |
51fa56b9 | 336 | abstract RETURN(XKWabstract); |
970ed795 EL |
337 | anyAttributes RETURN(XKWanyAttributes); |
338 | anyElement RETURN(XKWanyElement); | |
339 | attribute RETURN(XKWattribute); | |
340 | attributeFormQualified RETURN(XKWattributeFormQualified); | |
51fa56b9 | 341 | block RETURN(XKWblock); |
970ed795 EL |
342 | controlNamespace RETURN(XKWcontrolNamespace); |
343 | defaultForEmpty RETURN(XKWdefaultForEmpty); | |
344 | element RETURN(XKWelement); | |
345 | elementFormQualified RETURN(XKWelementFormQualified); | |
346 | embedValues RETURN(XKWembedValues); | |
347 | form RETURN(XKWform); | |
348 | list RETURN(XKWlist); | |
349 | name RETURN(XKWname); | |
350 | namespace RETURN(XKWnamespace); | |
351 | /* pi-or-comment */ | |
352 | text RETURN(XKWtext); | |
353 | untagged RETURN(XKWuntagged); | |
354 | useNil RETURN(XKWuseNil); | |
355 | useNumber RETURN(XKWuseNumber); | |
356 | useOrder RETURN(XKWuseOrder); | |
357 | useType RETURN(XKWuseType); | |
358 | useUnion RETURN(XKWuseUnion); | |
359 | whiteSpace RETURN(XKWwhiteSpace); | |
360 | XSD RETURN(XSD); | |
361 | ||
362 | as RETURN(XKWas); | |
363 | all RETURN(XKWall); | |
364 | in RETURN(XKWin); | |
365 | /* name mangling */ | |
366 | capitalized RETURN(XKWcapitalized); | |
367 | uncapitalized RETURN(XKWuncapitalized); | |
368 | lowercased RETURN(XKWlowercased); | |
369 | uppercased RETURN(XKWuppercased); | |
370 | ||
371 | qualified RETURN(XKWqualified); | |
372 | unqualified RETURN(XKWunqualified); /* ASN uses ABSENT */ | |
373 | except RETURN(XKWexcept); | |
374 | from RETURN(XKWfrom); | |
375 | prefix RETURN(XKWprefix); | |
376 | /* whitespace actions */ | |
377 | preserve RETURN(XKWpreserve); | |
378 | collapse RETURN(XKWcollapse); | |
379 | replace RETURN(XKWreplace); | |
380 | ||
381 | /* XSD:something */ | |
382 | string RETURN(XSDstring); | |
383 | normalizedString RETURN(XSDnormalizedString); | |
384 | token RETURN(XSDtoken); | |
385 | Name RETURN(XSDName); | |
386 | NMTOKEN RETURN(XSDNMTOKEN); | |
387 | NCName RETURN(XSDNCName); | |
388 | ID RETURN(XSDID); | |
389 | IDREF RETURN(XSDIDREF); | |
390 | ENTITY RETURN(XSDENTITY); | |
391 | hexBinary RETURN(XSDhexBinary); | |
392 | base64Binary RETURN(XSDbase64Binary); | |
393 | anyURI RETURN(XSDanyURI); | |
394 | language RETURN(XSDlanguage); | |
395 | integer RETURN(XSDinteger); | |
396 | positiveInteger RETURN(XSDpositiveInteger); | |
397 | nonPositiveInteger RETURN(XSDnonPositiveInteger); | |
398 | negativeInteger RETURN(XSDnegativeInteger); | |
399 | nonNegativeInteger RETURN(XSDnonNegativeInteger); | |
400 | /* already taken by BER: long RETURN(XSDlong);*/ | |
401 | unsignedLong RETURN(XSDunsignedLong); | |
402 | int RETURN(XSDint); | |
403 | unsignedInt RETURN(XSDunsignedInt); | |
404 | /* already taken by BER: short RETURN(XSDshort);*/ | |
405 | unsignedShort RETURN(XSDunsignedShort); | |
406 | byte RETURN(XSDbyte); | |
407 | unsignedByte RETURN(XSDunsignedByte); | |
408 | decimal RETURN(XSDdecimal); | |
409 | float RETURN(XSDfloat); | |
410 | double RETURN(XSDdouble); | |
411 | duration RETURN(XSDduration); | |
412 | dateTime RETURN(XSDdateTime); | |
413 | time RETURN(XSDtime); | |
414 | date RETURN(XSDdate); | |
415 | gYearMonth RETURN(XSDgYearMonth); | |
416 | gYear RETURN(XSDgYear); | |
417 | gMonthDay RETURN(XSDgMonthDay); | |
418 | gDay RETURN(XSDgDay); | |
419 | gMonth RETURN(XSDgMonth); | |
420 | NMTOKENS RETURN(XSDNMTOKENS); | |
421 | IDREFS RETURN(XSDIDREFS); | |
422 | ENTITIES RETURN(XSDENTITIES); | |
423 | QName RETURN(XSDQName); | |
424 | boolean RETURN(XSDboolean); | |
425 | ||
426 | anySimpleType RETURN(XSDanySimpleType); | |
427 | anyType RETURN(XSDanyType); | |
428 | ||
429 | } /* end XER keywords in INITIAL */ | |
430 | ||
431 | ||
432 | JSON { BEGIN(jsoncodec); RETURN(XKWjson); } | |
433 | ||
434 | <jsoncodec>{ | |
435 | [: \t] RETURN(*yytext); | |
436 | omit RETURN(XKWomit); | |
437 | as RETURN(XKWas); | |
438 | null RETURN(XKWnull); | |
439 | name RETURN(XKWname); | |
440 | value RETURN(XKWvalue); | |
441 | default RETURN(XKWdefault); | |
3abe9331 | 442 | extend RETURN(XKWextend); |
443 | metainfo RETURN(XKWmetainfo); | |
444 | for RETURN(XKWfor); | |
445 | unbound RETURN(XKWunbound); | |
970ed795 EL |
446 | [(] { BEGIN(jsonvalue); RETURN(XJsonValueStart); } |
447 | {IDENTIFIER} { yylval.str = mcopystr(yytext); RETURN(XAliasToken); } | |
448 | [^: \t] { rawAST_error("invalid JSON token"); } | |
449 | } | |
450 | ||
451 | <jsonvalue>{ | |
3abe9331 | 452 | [\\][\\][)] { /* \\) -> \) would not work with the other rules */ |
453 | yylval.str = mcopystr("\\)"); | |
454 | RETURN(XJsonValueSegment); | |
455 | } | |
456 | [\\]. { /* \) -> ), all others are treated literally */ | |
970ed795 EL |
457 | if (yytext[1] == ')') yylval.str = mcopystr(")"); |
458 | else yylval.str = mcopystr(yytext); | |
3abe9331 | 459 | RETURN(XJsonValueSegment); |
970ed795 EL |
460 | } |
461 | [)] { BEGIN(jsoncodec); RETURN(XJsonValueEnd); } | |
462 | [\"][\"] { yylval.str = mcopystr("\\\""); RETURN(XJsonValueSegment); } | |
463 | [^\"\\)]+ { yylval.str = mcopystr(yytext); RETURN(XJsonValueSegment); } | |
464 | } | |
465 | ||
466 | <INITIAL>{ | |
467 | length RETURN(XKWlength); | |
468 | accept RETURN(XKWaccept); | |
469 | long RETURN(XKWlong); | |
470 | short RETURN(XKWshort); | |
471 | indefinite RETURN(XKWindefinite); | |
472 | definite RETURN(XKWdefinite); | |
473 | } | |
474 | ||
475 | <textcodec>{ | |
476 | \'{MATCH_CHAR}*\' { | |
477 | yylloc.first_line = current_line; | |
478 | yylloc.first_column = current_column; | |
479 | current_column++; | |
480 | bool backslash_flag = false; | |
481 | yylval.str = memptystr(); | |
3abe9331 | 482 | for (size_t i = 1; i < yyleng - 1; ) { |
970ed795 EL |
483 | if (!backslash_flag && (yytext[i] == '\'' || yytext[i] == '"') && |
484 | yytext[i + 1] == yytext[i]) { | |
485 | /* transform '' -> \' and "" -> \" */ | |
486 | yylval.str = mputc(yylval.str, '\\'); | |
487 | yylval.str = mputc(yylval.str, yytext[i]); | |
488 | current_column += 2; | |
489 | i += 2; | |
490 | } else if (yytext[i] == '\r' && yytext[i + 1] == '\n') { | |
491 | /* handle the CR-LF sequence as a single newline */ | |
492 | yylval.str = mputstr(yylval.str, "\r\n"); | |
493 | current_line++; | |
494 | current_column = 0; | |
495 | backslash_flag = false; | |
496 | i += 2; | |
497 | } else { | |
498 | yylval.str = mputc(yylval.str, yytext[i]); | |
499 | if (yytext[i] == '\r' || yytext[i] == '\n') { | |
500 | current_line++; | |
501 | current_column = 0; | |
502 | } else current_column++; | |
503 | if (backslash_flag) backslash_flag = false; | |
504 | else if (yytext[i] == '\\') backslash_flag = true; | |
505 | i++; | |
506 | } | |
507 | } | |
508 | current_column++; | |
509 | yylloc.last_line = current_line; | |
510 | yylloc.last_column = current_column; | |
511 | return Xtoken; | |
512 | } | |
513 | ||
514 | length RETURN(XLengthToken); | |
515 | repeatable RETURN(XRepeatToken); | |
516 | convert RETURN(XConvertToken); | |
517 | lower_case RETURN(XLowerToken); | |
518 | upper_case RETURN(XUpperToken); | |
519 | just RETURN(XJustToken); | |
520 | left RETURN(XLeftToken); | |
521 | right RETURN(XRightToken); | |
522 | center RETURN(XCenterToken); | |
523 | leading0 RETURN(XLeadingToken); | |
524 | true RETURN(XTrueToken); | |
525 | false RETURN(XFalseToken); | |
526 | case_sensitive RETURN(XSensitivToken); | |
527 | case_insensitive RETURN(XInSensitivToken); | |
528 | {RPAREN} {BEGIN(INITIAL);RETURN(*yytext);} | |
529 | } /* end <textcodec> */ | |
530 | ||
531 | <INITIAL,textcodec,rawcodec>{ | |
532 | {IDENTIFIER} { | |
533 | yylval.identifier = new Identifier(Identifier::ID_TTCN, | |
534 | string(yyleng, yytext)); | |
535 | RETURN(XIdentifier); | |
536 | } | |
537 | . RETURN(*yytext); | |
538 | <<EOF>> { | |
539 | /* we must set the fake length 1 in order to report the single column | |
540 | * number of the unexpected EOF in error messages */ | |
541 | yyleng = 1; | |
542 | RETURN(EOF); | |
543 | } | |
544 | } | |
545 | ||
546 | %% | |
547 | ||
548 | void free_rawAST_field_list(rawAST_field_list *ptr) | |
549 | { | |
550 | if (ptr != NULL) { | |
551 | for (int i = 0; i < ptr->nElements; i++) delete ptr->names[i]; | |
552 | Free(ptr->names); | |
553 | Free(ptr); | |
554 | } | |
555 | } | |
556 | ||
557 | rawAST_single_tag* | |
558 | link_rawAST_single_tag(rawAST_single_tag* dst, rawAST_single_tag* src){ | |
559 | rawAST_single_tag* retv; | |
560 | if (src==NULL) return NULL; | |
561 | if (dst == src) return dst; | |
562 | // if (dst!=NULL) free_rawAST_single_tag(dst); | |
563 | ALLOCATE_IF_NULL(retv, dst, rawAST_single_tag); | |
564 | retv->fieldName=src->fieldName; | |
565 | retv->nElements=src->nElements; | |
566 | retv->keyList=src->keyList; | |
567 | return retv; | |
568 | } | |
569 | ||
570 | void | |
571 | free_rawAST_single_tag(rawAST_single_tag* spec){ | |
572 | int i; | |
573 | if(spec->fieldName) delete spec->fieldName; | |
574 | for (i=0; i<spec->nElements; i++) { | |
575 | free_rawAST_tag_field_value(&spec->keyList[i]); | |
576 | } | |
577 | if(spec->nElements) Free(spec->keyList); | |
578 | // init_rawAST_single_tag(spec); | |
579 | } | |
580 | ||
581 | void | |
582 | free_rawAST_tag_field_value(rawAST_tag_field_value* spec){ | |
583 | free_rawAST_field_list(spec->keyField); | |
584 | Free(spec->value); | |
585 | delete spec->v_value; | |
586 | // init_rawAST_tag_field_value(spec); | |
587 | } | |
588 | ||
589 | rawAST_tag_field_value* | |
590 | link_rawAST_tag_field_value(rawAST_tag_field_value* dst, rawAST_tag_field_value* src){ | |
591 | rawAST_tag_field_value* retv; | |
592 | if (src==NULL) return NULL; | |
593 | if (dst == src) return dst; | |
594 | ALLOCATE_IF_NULL(retv, dst, rawAST_tag_field_value); | |
595 | retv->keyField = src->keyField; | |
596 | retv->value = src->value; | |
597 | retv->v_value = src->v_value; | |
598 | return retv; | |
599 | } | |
600 | ||
601 | rawAST_tag_list* | |
602 | link_rawAST_tag_list(rawAST_tag_list* dst, rawAST_tag_list* src){ | |
603 | rawAST_tag_list* retv; | |
604 | if (src==NULL) return NULL; | |
605 | if (dst == src) return dst; | |
606 | ALLOCATE_IF_NULL(retv, dst, rawAST_tag_list); | |
607 | retv->nElements=src->nElements; | |
608 | retv->tag=src->tag; | |
609 | return retv; | |
610 | } | |
611 | ||
612 | rawAST_tag_field_value* | |
613 | init_rawAST_tag_field_value(rawAST_tag_field_value* spec){ | |
614 | rawAST_tag_field_value* retv; | |
615 | ALLOCATE_IF_NULL(retv, spec, rawAST_tag_field_value); | |
616 | retv->keyField=NULL; | |
617 | retv->value=NULL; | |
618 | retv->v_value=NULL; | |
619 | return retv; | |
620 | } | |
621 | ||
622 | void free_rawAST_tag_list(rawAST_tag_list* spec){ | |
623 | int i; | |
624 | if (spec==NULL) return; | |
625 | for (i=0; i<spec->nElements; i++) { | |
626 | free_rawAST_single_tag(&spec->tag[i]); | |
627 | } | |
628 | Free(spec->tag); | |
629 | // init_rawAST_tag_list(spec); | |
630 | } | |
631 | ||
632 | /* See RawAST.hh */ | |
633 | int parse_rawAST(RawAST *par, TextAST *textpar, XerAttributes *xerpar, | |
634 | BerAST* berpar, JsonAST* jsonpar, const Ttcn::AttributeSpec& attrib, | |
635 | int l_multip, const Common::Module* mod, bool &raw_found, bool &text_found, | |
636 | bool &xer_found, bool &ber_found, bool &json_found) | |
637 | { | |
638 | rawstruct=par; | |
639 | textstruct=textpar; | |
640 | xerstruct = xerpar; | |
641 | berstruct = berpar; | |
642 | jsonstruct = jsonpar; | |
643 | ||
644 | length_multiplier=l_multip; | |
645 | infile = attrib.get_filename(); | |
646 | current_line = attrib.get_first_line(); | |
647 | /* skip the leading " of the attribute value */ | |
648 | current_column = attrib.get_first_column() + 1; | |
649 | mymod=mod; | |
650 | raw_f =false; | |
651 | text_f=false; | |
652 | xer_f =false; | |
653 | ber_f =false; | |
654 | json_f = false; | |
655 | const string& s = attrib.get_spec(); | |
656 | #ifndef NDEBUG | |
657 | if (rawAST_debug) { | |
658 | fprintf(stderr, "*** raw=[%s]\n", s.c_str()); | |
659 | } | |
660 | #endif | |
661 | struct yy_buffer_state *flex_buffer = yy_scan_bytes(s.c_str(), s.size()); | |
662 | if (!flex_buffer) { | |
663 | FATAL_ERROR("parse_rawAST(): flex buffer creation failed"); | |
664 | } | |
665 | BEGIN(INITIAL); | |
666 | int retn=rawAST_parse(); | |
667 | yylex_destroy(); | |
668 | if(!raw_found) raw_found=raw_f || (!text_f && !xer_f && !ber_f && !json_f); | |
669 | // if none found, pretend some RAW attribute was found | |
670 | if(!text_found) text_found=text_f; | |
671 | if(!xer_found) xer_found=xer_f; | |
672 | if(!ber_found) ber_found=ber_f; | |
673 | if (!json_found) json_found = json_f; | |
674 | ||
675 | return retn; | |
676 | } | |
677 | ||
678 | void rawAST_error(const char *str) | |
679 | { | |
680 | Location loc(infile, yylloc); | |
681 | if (*yytext) { | |
682 | // the most recently parsed token is known | |
3f84031e | 683 | loc.warning("in variant attribute, at or before token `%s': %s", yytext, str); |
970ed795 EL |
684 | } else { |
685 | // the most recently parsed token is unknown | |
3f84031e | 686 | loc.warning("in variant attribute: %s", str); |
970ed795 EL |
687 | } |
688 | } | |
689 | ||
690 | /* | |
691 | Local Variables: | |
692 | mode: C | |
693 | indent-tabs-mode: nil | |
694 | c-basic-offset: 4 | |
695 | End: | |
696 | */ |