1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
15 * Szabo, Janos Zoltan – initial implementation
17 * Zalanyi, Balazs Andor
19 ******************************************************************************/
21 %option never-interactive
26 #include "../../common/memory.h"
29 #include "../Setting.hh"
30 #include "../Value.hh"
33 #include "../XerAttributes.hh"
34 #include "rawASTspec.h"
35 // the next one is the header generated from the .y
36 #include "rawAST.tab.hh"
37 #include "AST_ttcn3.hh"
38 #include "Attributes.hh"
41 using namespace Common;
43 #define ALLOCATE_IF_NULL(retv, oldptr, ptype) \
45 retv = (ptype*)Malloc(sizeof(ptype)); \
49 const Common::Module *mymod;
52 XerAttributes *xerstruct;
60 int length_multiplier;
62 extern void rawAST_error(const char *str); /* defined in this file */
63 extern int rawAST_parse(); /* in rawAST.tab.cc, generated from rawAST.y */
65 //rawAST_full_spec rawAST_result;
66 //rawAST_encoding_spec rawAST_partial_result;
68 extern int rawAST_debug;
70 #define yylval rawAST_lval
71 #define yylloc rawAST_lloc
73 extern YYLTYPE yylloc;
75 /* always points to the first character of the regexp to be recognized */
76 static int current_line, current_column;
78 static void update_lloc()
80 yylloc.first_line = current_line;
81 yylloc.first_column = current_column;
82 current_column += yyleng;
83 yylloc.last_line = current_line;
84 yylloc.last_column = current_column;
87 #define RETURN(retv) update_lloc(); return retv
93 LINECOMMENT "//"[^\r\n]*
100 FLOAT ({NUMBER}\.[0-9]+)|((({NUMBER}(\.[0-9]+)?)|(\.[0-9]+))[Ee][+-]?{NUMBER})
101 NUMBER 0|([1-9][0-9]*)
102 IDENTIFIER [A-Za-z][A-Za-z0-9_]*
104 CHAR [^\"\\]|\\[^\"]|{DQUOTE}{DQUOTE}
105 MATCH_CHAR [^'\\]|"''"|\\(.|\n)
108 /* start conditions (x: exclusive) */
117 int comment_caller = INITIAL;
119 <INITIAL,textcodec,rawcodec>{ /* all but ccomment */
121 yylloc.first_line = current_line;
122 yylloc.first_column = current_column;
123 current_column += yyleng;
124 comment_caller = YY_START;
128 {WHITESPACE}|{LINECOMMENT} current_column += yyleng;
130 } /* end <all but ccomment> */
132 <*>{NEWLINE} current_line++; current_column = 0;
135 "*/" current_column += yyleng; BEGIN(comment_caller);
138 yylloc.last_line = current_line;
139 yylloc.last_column = current_column;
140 Location loc(infile, yylloc);
141 loc.error("Unterminated block comment in variant attribute");
146 <INITIAL,textcodec,rawcodec>{NUMBER} {
148 Location loc(infile, yylloc);
149 yylval.intval = string2Int(yytext, loc);
157 Location loc(infile, yylloc);
158 yylval.floatval = string2Real(yytext, loc);
161 true { yylval.boolval = true;
162 RETURN(XBooleanConst);}
163 false { yylval.boolval = false;
164 RETURN(XBooleanConst);}
165 none { yylval.verdictval = Value::Verdict_NONE;
166 RETURN(XVerdictConst);}
167 pass { yylval.verdictval = Value::Verdict_PASS;
168 RETURN(XVerdictConst);}
169 inconc { yylval.verdictval = Value::Verdict_INCONC;
170 RETURN(XVerdictConst);}
171 fail { yylval.verdictval = Value::Verdict_FAIL;
172 RETURN(XVerdictConst);}
173 error { yylval.verdictval = Value::Verdict_ERROR;
174 RETURN(XVerdictConst);}
175 null RETURN(XNullKeyword);
176 NULL RETURN(XNULLKeyword);
177 omit RETURN(XOmitKeyword);
179 {DQUOTE}{CHAR}*{DQUOTE} {
180 yylloc.first_line = current_line;
181 /* we have to cheat because parse_charstring_value() expects one quotation
182 * mark character as delimiter, but {DQUOTE} matches two characters */
183 yylloc.first_column = current_column + 1;
185 bool backslash_flag = false;
186 yylval.str = memptystr();
187 for (size_t i = 2; i < yyleng - 2; ) {
188 if (!backslash_flag && (yytext[i] == '\\' || yytext[i] == '"') &&
189 yytext[i + 1] == '"' &&
190 (yytext[i + 2] == '\\' || yytext[i + 2] == '"') &&
191 yytext[i + 3] == '"') {
192 /* transform embedded escaped quotes: \"\" or """" -> "" */
193 /* we must use the octal notation to keep the column numbers in synch */
194 yylval.str = mputstr(yylval.str, "\\042");
197 } else if (yytext[i] == '\r' && yytext[i + 1] == '\n') {
198 /* handle the CR-LF sequence as a single newline */
199 yylval.str = mputstr(yylval.str, "\r\n");
202 backslash_flag = false;
205 yylval.str = mputc(yylval.str, yytext[i]);
206 if (yytext[i] == '\r' || yytext[i] == '\n') {
209 } else current_column++;
210 if (backslash_flag) backslash_flag = false;
211 else if (yytext[i] == '\\') backslash_flag = true;
216 yylloc.last_line = current_line;
217 yylloc.last_column = current_column - 1;
222 yytext[yyleng - 2] = '\0';
223 yylval.str = mcopystr(yytext + 1);
227 '[^\']*'B { /* a properly delimited bit string with incorrect content */
228 /* the backslash in the character class is redundant, but helps editors
229 * get the syntax highlighting right */
231 rawAST_error("invalid bitstring value");
232 yylval.str = memptystr();
237 yytext[yyleng - 2] = '\0';
238 yylval.str = mcopystr(yytext + 1);
242 '[^\']*'H { /* a properly delimited hex string with incorrect content */
244 rawAST_error("invalid hexstring value");
245 yylval.str = memptystr();
250 yytext[yyleng - 2] = '\0';
251 yylval.str = mcopystr(yytext + 1);
255 '[^\']*'O { /* a properly delimited octet string with incorrect content */
257 rawAST_error("invalid octetstring value");
258 yylval.str = memptystr();
263 '[^\']*' { /* A string delimited by a pair of ' */
264 yytext[yyleng - 1] = '\0';
265 yylval.str = mcopystr(yytext + 1);
269 } /* end <rawcodec,INITIAL> */
271 /* RAW encoder keywords */
272 PADDING { BEGIN(rawcodec); RETURN(XPaddingKeyword); }
273 PREPADDING { BEGIN(rawcodec); RETURN(XPrePaddingKeyword); }
274 PADDING_PATTERN { BEGIN(rawcodec); RETURN(XPaddingPatternKeyword); }
275 PADDALL RETURN(XPaddAllKeyword);
276 FIELDORDER { BEGIN(rawcodec); RETURN(XFieldOrderKeyword); }
277 EXTENSION_BIT { BEGIN(rawcodec); RETURN(XExtensionBitKeyword); }
278 EXTENSION_BIT_GROUP { BEGIN(rawcodec); RETURN(XExtensionBitGroupKeyword); }
279 LENGTHTO { BEGIN(rawcodec); RETURN(XLengthToKeyword); }
280 POINTERTO { BEGIN(rawcodec); RETURN(XPointerToKeyword); }
281 UNIT { BEGIN(rawcodec); RETURN(XUnitKeyword); }
282 PTRUNIT { BEGIN(rawcodec); RETURN(XPtrUnitKeyword); }
283 REPEATABLE { BEGIN(rawcodec); RETURN(XRepeatableKeyword); }
284 PTROFFSET { BEGIN(rawcodec); RETURN(XPtrOffsetKeyword); }
285 LENGTHINDEX { BEGIN(rawcodec); RETURN(XLengthIndexKeyword); }
286 TAG { BEGIN(rawcodec); RETURN(XTagKeyword); }
287 CROSSTAG { BEGIN(rawcodec); RETURN(XCrossTagKeyword); }
288 PRESENCE { BEGIN(rawcodec); RETURN(XPresenceKeyword); }
289 FIELDLENGTH { BEGIN(rawcodec); RETURN(XFieldLengthKeyword); }
290 FORMAT { BEGIN(rawcodec); RETURN(XFieldLengthKeyword); }
291 ALIGN { BEGIN(rawcodec); RETURN(XAlignKeyword); }
292 BYTEORDER { BEGIN(rawcodec); RETURN(XByteOrderKeyword); }
293 COMP { BEGIN(rawcodec); RETURN(XCompKeyword); }
294 BITORDER { BEGIN(rawcodec); RETURN(XBitOrderKeyword); }
295 BITORDERINFIELD { BEGIN(rawcodec); RETURN(XBitOrderInFieldKeyword); }
296 BITORDERINOCTET { BEGIN(rawcodec); RETURN(XBitOrderInOctetKeyword); }
297 HEXORDER { BEGIN(rawcodec); RETURN(XHexOrderKeyword); }
298 TOPLEVEL { BEGIN(rawcodec); RETURN(XToplevelKeyword); }
299 IntX { RETURN(XIntXKeyword); }
300 bit { RETURN(XBitKeyword); }
301 unsigned { RETURN(XUnsignedKeyword); }
304 yes { yylval.enumval = XDEFYES; RETURN(XYes); }
305 no { yylval.enumval = XDEFNO; RETURN(XNo); }
306 reverse { yylval.enumval = XDEFREVERSE; RETURN (XReverse); }
307 msb { yylval.enumval = XDEFMSB; RETURN(XMsb); }
308 lsb { yylval.enumval = XDEFLSB; RETURN(XLsb); }
309 bits { yylval.enumval = 1; RETURN(XBits); }
310 bit { yylval.enumval = 1; RETURN(XBits); }
311 octets { yylval.enumval = 8; RETURN(XOctets); }
312 octet { yylval.enumval = 8; RETURN(XOctets); }
313 nibble { yylval.enumval = 4; RETURN(XOctets); }
314 word16 { yylval.enumval = 16; RETURN(XOctets); }
315 dword32 { yylval.enumval = 32; RETURN(XOctets); }
316 elements { yylval.enumval = -1; RETURN(XOctets); }
317 variable { yylval.intval = 0; RETURN(XNumber);}
318 IEEE754[ ]double { yylval.intval = 64; RETURN(XNumber);}
319 IEEE754[ ]float { yylval.intval = 32; RETURN(XNumber);}
320 left { yylval.enumval = XDEFLEFT; RETURN(XLeft); }
321 right { yylval.enumval = XDEFRIGHT; RETURN(XRight); }
322 nosign { yylval.enumval = XDEFUNSIGNED; RETURN(XUnsigned); }
323 2scompl { yylval.enumval = XDEFCOMPL; RETURN(XCompl); }
324 signbit { yylval.enumval = XDEFSIGNBIT; RETURN(XSignbit); }
325 first { yylval.enumval = XDEFFIRST; RETURN(XFirst); }
326 last { yylval.enumval = XDEFLAST; RETURN(XLast); }
327 low { yylval.enumval = XDEFLOW; RETURN(XLow); }
328 high { yylval.enumval = XDEFHIGH; RETURN(XHigh); }
329 OTHERWISE RETURN(XOtherwise);
331 {RPAREN} {BEGIN(INITIAL);RETURN(*yytext);}
333 } /* end <rawcodec> */
335 /* TEXT codec starters */
336 BEGIN { BEGIN(textcodec);RETURN(XBeginKeyword);}
337 END { BEGIN(textcodec);RETURN(XEndKeyword);}
338 SEPARATOR { BEGIN(textcodec);RETURN(XSeparatorKeyword);}
339 TEXT_CODING { BEGIN(textcodec);RETURN(XCodingKeyword); }
343 /* XER attributes are not as well delimited like TEXT/RAW,
344 * so no start condition for them (it would be difficult to determine
345 * when to return to INITIAL) */
347 /* First, the "starter" attributes */
348 abstract RETURN(XKWabstract);
349 anyAttributes RETURN(XKWanyAttributes);
350 anyElement RETURN(XKWanyElement);
351 attribute RETURN(XKWattribute);
352 attributeFormQualified RETURN(XKWattributeFormQualified);
353 block RETURN(XKWblock);
354 controlNamespace RETURN(XKWcontrolNamespace);
355 defaultForEmpty RETURN(XKWdefaultForEmpty);
356 element RETURN(XKWelement);
357 elementFormQualified RETURN(XKWelementFormQualified);
358 embedValues RETURN(XKWembedValues);
359 form RETURN(XKWform);
360 list RETURN(XKWlist);
361 name RETURN(XKWname);
362 namespace RETURN(XKWnamespace);
364 text RETURN(XKWtext);
365 untagged RETURN(XKWuntagged);
366 useNil RETURN(XKWuseNil);
367 useNumber RETURN(XKWuseNumber);
368 useOrder RETURN(XKWuseOrder);
369 useType RETURN(XKWuseType);
370 useUnion RETURN(XKWuseUnion);
371 whiteSpace RETURN(XKWwhiteSpace);
378 capitalized RETURN(XKWcapitalized);
379 uncapitalized RETURN(XKWuncapitalized);
380 lowercased RETURN(XKWlowercased);
381 uppercased RETURN(XKWuppercased);
383 qualified RETURN(XKWqualified);
384 unqualified RETURN(XKWunqualified); /* ASN uses ABSENT */
385 except RETURN(XKWexcept);
386 from RETURN(XKWfrom);
387 prefix RETURN(XKWprefix);
388 /* whitespace actions */
389 preserve RETURN(XKWpreserve);
390 collapse RETURN(XKWcollapse);
391 replace RETURN(XKWreplace);
394 string RETURN(XSDstring);
395 normalizedString RETURN(XSDnormalizedString);
396 token RETURN(XSDtoken);
397 Name RETURN(XSDName);
398 NMTOKEN RETURN(XSDNMTOKEN);
399 NCName RETURN(XSDNCName);
401 IDREF RETURN(XSDIDREF);
402 ENTITY RETURN(XSDENTITY);
403 hexBinary RETURN(XSDhexBinary);
404 base64Binary RETURN(XSDbase64Binary);
405 anyURI RETURN(XSDanyURI);
406 language RETURN(XSDlanguage);
407 integer RETURN(XSDinteger);
408 positiveInteger RETURN(XSDpositiveInteger);
409 nonPositiveInteger RETURN(XSDnonPositiveInteger);
410 negativeInteger RETURN(XSDnegativeInteger);
411 nonNegativeInteger RETURN(XSDnonNegativeInteger);
412 /* already taken by BER: long RETURN(XSDlong);*/
413 unsignedLong RETURN(XSDunsignedLong);
415 unsignedInt RETURN(XSDunsignedInt);
416 /* already taken by BER: short RETURN(XSDshort);*/
417 unsignedShort RETURN(XSDunsignedShort);
418 byte RETURN(XSDbyte);
419 unsignedByte RETURN(XSDunsignedByte);
420 decimal RETURN(XSDdecimal);
421 float RETURN(XSDfloat);
422 double RETURN(XSDdouble);
423 duration RETURN(XSDduration);
424 dateTime RETURN(XSDdateTime);
425 time RETURN(XSDtime);
426 date RETURN(XSDdate);
427 gYearMonth RETURN(XSDgYearMonth);
428 gYear RETURN(XSDgYear);
429 gMonthDay RETURN(XSDgMonthDay);
430 gDay RETURN(XSDgDay);
431 gMonth RETURN(XSDgMonth);
432 NMTOKENS RETURN(XSDNMTOKENS);
433 IDREFS RETURN(XSDIDREFS);
434 ENTITIES RETURN(XSDENTITIES);
435 QName RETURN(XSDQName);
436 boolean RETURN(XSDboolean);
438 anySimpleType RETURN(XSDanySimpleType);
439 anyType RETURN(XSDanyType);
441 } /* end XER keywords in INITIAL */
444 JSON { BEGIN(jsoncodec); RETURN(XKWjson); }
447 [: \t] RETURN(*yytext);
448 omit RETURN(XKWomit);
450 null RETURN(XKWnull);
451 name RETURN(XKWname);
452 value RETURN(XKWvalue);
453 default RETURN(XKWdefault);
454 extend RETURN(XKWextend);
455 metainfo RETURN(XKWmetainfo);
457 unbound RETURN(XKWunbound);
458 [(] { BEGIN(jsonvalue); RETURN(XJsonValueStart); }
459 {IDENTIFIER} { yylval.str = mcopystr(yytext); RETURN(XAliasToken); }
460 [^: \t] { rawAST_error("invalid JSON token"); }
464 [\\][\\][)] { /* \\) -> \) would not work with the other rules */
465 yylval.str = mcopystr("\\)");
466 RETURN(XJsonValueSegment);
468 [\\]. { /* \) -> ), all others are treated literally */
469 if (yytext[1] == ')') yylval.str = mcopystr(")");
470 else yylval.str = mcopystr(yytext);
471 RETURN(XJsonValueSegment);
473 [)] { BEGIN(jsoncodec); RETURN(XJsonValueEnd); }
474 [\"][\"] { yylval.str = mcopystr("\\\""); RETURN(XJsonValueSegment); }
475 [^\"\\)]+ { yylval.str = mcopystr(yytext); RETURN(XJsonValueSegment); }
479 length RETURN(XKWlength);
480 accept RETURN(XKWaccept);
481 long RETURN(XKWlong);
482 short RETURN(XKWshort);
483 indefinite RETURN(XKWindefinite);
484 definite RETURN(XKWdefinite);
489 yylloc.first_line = current_line;
490 yylloc.first_column = current_column;
492 bool backslash_flag = false;
493 yylval.str = memptystr();
494 for (size_t i = 1; i < yyleng - 1; ) {
495 if (!backslash_flag && (yytext[i] == '\'' || yytext[i] == '"') &&
496 yytext[i + 1] == yytext[i]) {
497 /* transform '' -> \' and "" -> \" */
498 yylval.str = mputc(yylval.str, '\\');
499 yylval.str = mputc(yylval.str, yytext[i]);
502 } else if (yytext[i] == '\r' && yytext[i + 1] == '\n') {
503 /* handle the CR-LF sequence as a single newline */
504 yylval.str = mputstr(yylval.str, "\r\n");
507 backslash_flag = false;
510 yylval.str = mputc(yylval.str, yytext[i]);
511 if (yytext[i] == '\r' || yytext[i] == '\n') {
514 } else current_column++;
515 if (backslash_flag) backslash_flag = false;
516 else if (yytext[i] == '\\') backslash_flag = true;
521 yylloc.last_line = current_line;
522 yylloc.last_column = current_column;
526 length RETURN(XLengthToken);
527 repeatable RETURN(XRepeatToken);
528 convert RETURN(XConvertToken);
529 lower_case RETURN(XLowerToken);
530 upper_case RETURN(XUpperToken);
531 just RETURN(XJustToken);
532 left RETURN(XLeftToken);
533 right RETURN(XRightToken);
534 center RETURN(XCenterToken);
535 leading0 RETURN(XLeadingToken);
536 true RETURN(XTrueToken);
537 false RETURN(XFalseToken);
538 case_sensitive RETURN(XSensitivToken);
539 case_insensitive RETURN(XInSensitivToken);
540 {RPAREN} {BEGIN(INITIAL);RETURN(*yytext);}
541 } /* end <textcodec> */
543 <INITIAL,textcodec,rawcodec>{
545 yylval.identifier = new Identifier(Identifier::ID_TTCN,
546 string(yyleng, yytext));
551 /* we must set the fake length 1 in order to report the single column
552 * number of the unexpected EOF in error messages */
560 void free_rawAST_field_list(rawAST_field_list *ptr)
563 for (int i = 0; i < ptr->nElements; i++) delete ptr->names[i];
570 link_rawAST_single_tag(rawAST_single_tag* dst, rawAST_single_tag* src){
571 rawAST_single_tag* retv;
572 if (src==NULL) return NULL;
573 if (dst == src) return dst;
574 // if (dst!=NULL) free_rawAST_single_tag(dst);
575 ALLOCATE_IF_NULL(retv, dst, rawAST_single_tag);
576 retv->fieldName=src->fieldName;
577 retv->nElements=src->nElements;
578 retv->keyList=src->keyList;
583 free_rawAST_single_tag(rawAST_single_tag* spec){
585 if(spec->fieldName) delete spec->fieldName;
586 for (i=0; i<spec->nElements; i++) {
587 free_rawAST_tag_field_value(&spec->keyList[i]);
589 if(spec->nElements) Free(spec->keyList);
590 // init_rawAST_single_tag(spec);
594 free_rawAST_tag_field_value(rawAST_tag_field_value* spec){
595 free_rawAST_field_list(spec->keyField);
597 delete spec->v_value;
598 // init_rawAST_tag_field_value(spec);
601 rawAST_tag_field_value*
602 link_rawAST_tag_field_value(rawAST_tag_field_value* dst, rawAST_tag_field_value* src){
603 rawAST_tag_field_value* retv;
604 if (src==NULL) return NULL;
605 if (dst == src) return dst;
606 ALLOCATE_IF_NULL(retv, dst, rawAST_tag_field_value);
607 retv->keyField = src->keyField;
608 retv->value = src->value;
609 retv->v_value = src->v_value;
614 link_rawAST_tag_list(rawAST_tag_list* dst, rawAST_tag_list* src){
615 rawAST_tag_list* retv;
616 if (src==NULL) return NULL;
617 if (dst == src) return dst;
618 ALLOCATE_IF_NULL(retv, dst, rawAST_tag_list);
619 retv->nElements=src->nElements;
624 rawAST_tag_field_value*
625 init_rawAST_tag_field_value(rawAST_tag_field_value* spec){
626 rawAST_tag_field_value* retv;
627 ALLOCATE_IF_NULL(retv, spec, rawAST_tag_field_value);
634 void free_rawAST_tag_list(rawAST_tag_list* spec){
636 if (spec==NULL) return;
637 for (i=0; i<spec->nElements; i++) {
638 free_rawAST_single_tag(&spec->tag[i]);
641 // init_rawAST_tag_list(spec);
645 int parse_rawAST(RawAST *par, TextAST *textpar, XerAttributes *xerpar,
646 BerAST* berpar, JsonAST* jsonpar, const Ttcn::AttributeSpec& attrib,
647 int l_multip, const Common::Module* mod, bool &raw_found, bool &text_found,
648 bool &xer_found, bool &ber_found, bool &json_found)
654 jsonstruct = jsonpar;
656 length_multiplier=l_multip;
657 infile = attrib.get_filename();
658 current_line = attrib.get_first_line();
659 /* skip the leading " of the attribute value */
660 current_column = attrib.get_first_column() + 1;
667 const string& s = attrib.get_spec();
670 fprintf(stderr, "*** raw=[%s]\n", s.c_str());
673 struct yy_buffer_state *flex_buffer = yy_scan_bytes(s.c_str(), s.size());
675 FATAL_ERROR("parse_rawAST(): flex buffer creation failed");
678 int retn=rawAST_parse();
680 if(!raw_found) raw_found=raw_f || (!text_f && !xer_f && !ber_f && !json_f);
681 // if none found, pretend some RAW attribute was found
682 if(!text_found) text_found=text_f;
683 if(!xer_found) xer_found=xer_f;
684 if(!ber_found) ber_found=ber_f;
685 if (!json_found) json_found = json_f;
690 void rawAST_error(const char *str)
692 Location loc(infile, yylloc);
694 // the most recently parsed token is known
695 if (warnings_for_bad_variants) {
696 loc.warning("in variant attribute, at or before token `%s': %s", yytext, str);
698 loc.error("in variant attribute, at or before token `%s': %s", yytext, str);
701 // the most recently parsed token is unknown
702 if (warnings_for_bad_variants) {
703 loc.warning("in variant attribute: %s", str);
705 loc.error("in variant attribute: %s", str);
713 indent-tabs-mode: nil