Sync with 5.4.0
[deliverable/titan.core.git] / compiler2 / ttcn3 / compiler.l
1 /******************************************************************************
2 * Copyright (c) 2000-2015 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 %{
12
13 /* Tokenizer for TTCN-3 Core Language */
14
15 #include "../../common/dbgnew.hh"
16 #include "compiler.h"
17 #include "../string.hh"
18 #include "../CompilerError.hh"
19 #include "../Real.hh"
20 #include "../Value.hh"
21 #include "AST_ttcn3.hh"
22 #include "Ttcnstuff.hh" // at least for PortTypeBody::PortOperationMode_t
23 #include "Statement.hh" // for Statement::statementtype_t
24 #include "Attributes.hh"
25
26 #include <string.h>
27 #include <ctype.h>
28 #include <openssl/md5.h>
29
30 namespace Common {
31 class IndexedValue;
32 class Location;
33 }
34
35 namespace Ttcn {
36 class ParamRedirect;
37 class Statement;
38 class AltGuard;
39 class IfClause;
40 class IfClauses;
41 class NamedTemplate;
42 class NamedTemplates;
43 class IndexedTemplate;
44 class IndexedTemplates;
45 class Templates;
46 class CompTypeRefList;
47 }
48
49 using namespace Common;
50 using namespace Ttcn;
51
52 #include "compiler.tab.hh"
53
54 #define yylval ttcn3_lval
55 #define yylloc ttcn3_lloc
56
57 /* global variable indicating the location of the returned token to bison */
58 extern YYLTYPE yylloc;
59
60 extern bool is_erroneous_parsed;
61
62 /* always points to the first character of the regexp to be recognized */
63 static int current_line, current_column;
64
65 /* when reporting an error in linemarker or preprocessor
66 * directive the real file name and line number is needed */
67 static const char* real_infile;
68 /* real_lineno = current_line + real_lineno_offset */
69 static int real_lineno_offset;
70
71 static bool dot_flag = false;
72 /* type of the backup token (that was found after a dot) */
73 static int backup_token;
74 /* semantic value of the backup token */
75 static YYSTYPE backup_lval;
76 /* location of the backup token */
77 static YYLTYPE backup_lloc;
78
79 static MD5_CTX md5_ctx;
80
81 static void fill_location()
82 {
83 yylloc.first_line = current_line;
84 yylloc.first_column = current_column;
85 current_column += yyleng;
86 yylloc.last_line = current_line;
87 yylloc.last_column = current_column;
88 }
89
90 static void update_md5()
91 {
92 MD5_Update(&md5_ctx, yytext, yyleng);
93 MD5_Update(&md5_ctx, " ", 1);
94 }
95
96 #define RETURN_SAVED_DOT \
97 do { \
98 yytext[0] = '\0'; \
99 yylloc.first_line = dot_line; \
100 yylloc.first_column = dot_column; \
101 yylloc.last_line = dot_line; \
102 yylloc.last_column = dot_column + 1; \
103 return '.'; \
104 } while (0)
105
106 /* return macro for simple tokens without semantic value */
107 #define RETURN(ret_val) \
108 do { \
109 update_md5(); \
110 fill_location(); \
111 if (dot_flag) { \
112 backup_token = ret_val; \
113 backup_lloc = yylloc; \
114 RETURN_SAVED_DOT; \
115 } else return ret_val; \
116 } while (0)
117
118 /* same as RETURN(ret_val) macro but without location update,
119 * usually a return after an error */
120 #define RETURN_NOLOCUPD(ret_val) \
121 do { \
122 update_md5(); \
123 if (dot_flag) { \
124 backup_token = ret_val; \
125 backup_lloc = yylloc; \
126 RETURN_SAVED_DOT; \
127 } else return ret_val; \
128 } while (0)
129
130 /* return macro for simple tokens with semantic value */
131 #define RETURN_LVAL(ret_val) \
132 do { \
133 update_md5(); \
134 fill_location(); \
135 if (dot_flag) { \
136 backup_token = ret_val; \
137 backup_lval = yylval; \
138 backup_lloc = yylloc; \
139 RETURN_SAVED_DOT; \
140 } else return ret_val; \
141 } while (0)
142
143 /* return macro for special tokens that are glued together with previous dot */
144 #define RETURN_DOT(ret_val) \
145 do { \
146 update_md5(); \
147 if (dot_flag) { \
148 dot_flag = false; \
149 yylloc.first_line = dot_line; \
150 yylloc.first_column = dot_column; \
151 current_column += yyleng; \
152 yylloc.last_line = current_line; \
153 yylloc.last_column = current_column; \
154 return Dot##ret_val; \
155 } else { \
156 fill_location(); \
157 return ret_val; \
158 } \
159 } while (0)
160
161 extern string *parse_charstring_value(const char *str, const Location& loc);
162
163 %}
164
165 NUMBER 0|([1-9][0-9]*)
166
167 FLOAT ({NUMBER}\.[0-9]+)|({NUMBER}(\.[0-9]+)?[Ee][+-]?{NUMBER})
168
169 IDENTIFIER [A-Za-z][A-Za-z0-9_]*
170
171 LINECOMMENT "//"[^\r\n]*
172
173 WHITESPACE [ \t\v\f]
174
175 NEWLINE \r|\n|\r\n
176
177 LINEMARKER {NUMBER}{WHITESPACE}+\"([^\\\"\r\n]|\\[^\r\n])*\"
178
179 TITAN "$#&&&(#TITANERRONEOUS$#&&^#% "
180
181 %x SC_blockcomment SC_cstring
182 %x SC_binstring SC_binstring_bad
183
184 %%
185 /* local variables of yylex() */
186 int start_line = 0, start_column = 0; /**< used by block comments and
187 string literals */
188 int dot_line = 0, dot_column = 0; /**< location of the previous '.' token */
189 /* variables used when processing binary strings */
190 expstring_t binstr = NULL; /**< the string itself */
191 bool valid_bit = false, /**< binstr is valid bitstring */
192 valid_oct = false, /**< binstr is valid octetstring */
193 half_oct = false, /**< binstr is not a valid octetstr but a valid hexstr */
194 contains_match = false, /**< binstr contains matching symbol */
195 contains_ws = false; /**< binstr contains whitespace characters */
196
197 if (dot_flag) {
198 if (backup_token == '.') {
199 /* Two dots were found in the previous call: the first one was returned,
200 * the second one is now in the backup. Let's assume that we have just
201 * found the second one. */
202 dot_line = backup_lloc.first_line;
203 dot_column = backup_lloc.first_column;
204 } else {
205 /* Return the token and its semantic value that was backed up after the
206 * last token (which was a dot). */
207 dot_flag = false;
208 yylval = backup_lval;
209 yylloc = backup_lloc;
210 return backup_token;
211 }
212 }
213
214
215 {TITAN} {
216 // hack: to avoid the erroneous parsing reporting a syntax error where it
217 // also lists TTCN3ModuleKeyword as a possible nonterminal to use
218 if (is_erroneous_parsed) {
219 RETURN(TitanErroneousHackKeyword);
220 } else {
221 Location loc(infile, current_line, current_column, current_line,
222 current_column + yyleng);
223 loc.error("Unexpected `%s'.", yytext);
224 }
225 }
226
227 /* Eat up comments and whitespaces */
228
229 "/*" {
230 start_line = current_line;
231 start_column = current_column;
232 current_column += 2;
233 BEGIN(SC_blockcomment);
234 }
235
236 <SC_blockcomment> /* -------- SC_blockcomment scope -------------- */
237 {
238
239 "*/" {
240 current_column += 2;
241 BEGIN(INITIAL);
242 }
243
244 {NEWLINE} {
245 current_line++;
246 current_column = 0;
247 }
248
249 . current_column++;
250
251 } /* SC_blockcomment */
252
253 {LINECOMMENT}?{NEWLINE} {
254 current_line++;
255 current_column = 0;
256 }
257
258 {LINECOMMENT} {
259 current_column += yyleng;
260 }
261
262 {WHITESPACE}+ current_column += yyleng;
263
264 /* C preprocessor line markers */
265
266 ^{WHITESPACE}*"#"({WHITESPACE}*"line")?{WHITESPACE}+{LINEMARKER}[^\r\n]*{NEWLINE} {
267 bool error_flag = false;
268 int real_lineno = current_line + real_lineno_offset;
269 /* skipping the leading whitespaces */
270 int marker_begin = 0;
271 while (yytext[marker_begin] != '#') marker_begin++;
272 /* skipping the trailing whitespaces and newline */
273 int marker_end = yyleng - 1;
274 while (yytext[marker_end] == '\r' || yytext[marker_end] == '\n' ||
275 yytext[marker_end] == ' ' || yytext[marker_end] == '\t') marker_end--;
276 marker_end++;
277 Location loc(real_infile, real_lineno, current_column + marker_begin,
278 real_lineno, current_column + marker_end);
279 Error_Context cntxt(&loc, "In preprocessor line marker");
280 /* parsing out the line number */
281 int lineno_begin = marker_begin + 1;
282 while (!isdigit((unsigned char)yytext[lineno_begin])) lineno_begin++;
283 int lineno_end = lineno_begin + 1;
284 while (isdigit((int)yytext[lineno_end])) lineno_end++;
285 errno = 0;
286 int new_lineno = strtol(yytext + lineno_begin, NULL, 10);
287 if (errno != 0) {
288 Location lineno_loc(real_infile, real_lineno, current_column + lineno_begin,
289 real_lineno, current_column + lineno_end);
290 string lineno_str(lineno_end - lineno_begin, yytext + lineno_begin);
291 lineno_loc.error("Line number `%s' is too large for being represented in "
292 "memory: %s", lineno_str.c_str(), strerror(errno));
293 error_flag = true;
294 }
295 /* parsing out the file name */
296 int filename_begin = lineno_end + 1;
297 while (yytext[filename_begin] != '"') filename_begin++;
298 filename_begin++;
299 int filename_end = filename_begin;
300 while (yytext[filename_end] != '"') {
301 if (yytext[filename_end] == '\\') filename_end += 2;
302 else filename_end++;
303 }
304 Location filename_loc(real_infile, real_lineno, current_column +
305 filename_begin - 1, real_lineno, current_column + filename_end + 1);
306 string filename_str(filename_end - filename_begin, yytext + filename_begin);
307 string *parsed_filename = parse_charstring_value(filename_str.c_str(),
308 filename_loc);
309 if (!parsed_filename) error_flag = true;
310 /* updating the line/column counters */
311 if (error_flag) {
312 /* the line marker is erroneous, use the real line numbers */
313 infile = real_infile;
314 current_line = real_lineno + 1;
315 real_lineno_offset = 0;
316 } else {
317 /* set the given line number */
318 infile = Location::add_source_file_name(*parsed_filename);
319 current_line = new_lineno;
320 real_lineno_offset = real_lineno + 1 - new_lineno;
321 }
322 current_column = 0;
323 delete parsed_filename;
324 }
325
326 ^{WHITESPACE}*"#"[^\r\n]* {
327 int real_lineno = current_line + real_lineno_offset;
328 /* skip the leading and trailing whitespaces */
329 int marker_begin = 0;
330 while (yytext[marker_begin] != '#') marker_begin++;
331 int marker_end = yyleng - 1;
332 while (yytext[marker_end] == ' ' || yytext[marker_end] == '\t') marker_end--;
333 marker_end++;
334 Location loc(real_infile, real_lineno, current_column + marker_begin,
335 real_lineno, current_column + marker_end);
336 loc.error("Invalid/unsupported preprocessor directive or line marker: `%s'",
337 string(marker_end - marker_begin, yytext + marker_begin).c_str());
338 current_column += yyleng;
339 }
340
341 /* Keywords */
342
343 action RETURN(ActionKeyword);
344 activate RETURN(ActivateKeyword);
345 address RETURN(AddressKeyword);
346 alive RETURN_DOT(AliveKeyword);
347 all RETURN(AllKeyword);
348 alt RETURN(AltKeyword);
349 altstep RETURN(AltstepKeyword);
350 and RETURN(AndKeyword);
351 and4b RETURN(And4bKeyword);
352 any RETURN(AnyKeyword);
353 anytype RETURN(AnyTypeKeyword);
354 apply RETURN_DOT(ApplyKeyword);
355 bitstring RETURN(BitStringKeyword);
356 boolean RETURN(BooleanKeyword);
357 break RETURN(BreakKeyword);
358 call RETURN_DOT(CallOpKeyword);
359 case RETURN(CaseKeyword);
360 catch RETURN_DOT(CatchOpKeyword);
361 char RETURN(CharKeyword);
362 charstring RETURN(CharStringKeyword);
363 check RETURN_DOT(CheckOpKeyword);
364 clear RETURN_DOT(ClearOpKeyword);
365 complement RETURN(ComplementKeyword);
366 component RETURN(ComponentKeyword);
367 connect RETURN(ConnectKeyword);
368 const RETURN(ConstKeyword);
369 continue RETURN(ContinueKeyword);
370 control RETURN(ControlKeyword);
371 create RETURN_DOT(CreateKeyword);
372 deactivate RETURN(DeactivateKeyword);
373 default RETURN(DefaultKeyword);
374 derefers RETURN(DerefersKeyword);
375 disconnect RETURN(DisconnectKeyword);
376 display RETURN(DisplayKeyword);
377 do RETURN(DoKeyword);
378 done RETURN_DOT(DoneKeyword);
379 else RETURN(ElseKeyword);
380 encode RETURN(EncodeKeyword);
381 enumerated RETURN(EnumKeyword);
382 error RETURN(ErrorKeyword);
383 except RETURN(ExceptKeyword);
384 exception RETURN(ExceptionKeyword);
385 execute RETURN(ExecuteKeyword);
386 extends RETURN(ExtendsKeyword);
387 extension RETURN(ExtensionKeyword);
388 external RETURN(ExtKeyword);
389 fail RETURN(FailKeyword);
390 false RETURN(FalseKeyword);
391 float RETURN(FloatKeyword);
392 for RETURN(ForKeyword);
393 friend RETURN(FriendKeyword);
394 from RETURN(FromKeyword);
395 function RETURN(FunctionKeyword);
396 getcall RETURN_DOT(GetCallOpKeyword);
397 getreply RETURN_DOT(GetReplyOpKeyword);
398 getverdict RETURN(GetVerdictKeyword);
399 goto RETURN(GotoKeyword);
400 group RETURN(GroupKeyword);
401 halt RETURN_DOT(HaltKeyword);
402 hexstring RETURN(HexStringKeyword);
403 if RETURN(IfKeyword);
404 ifpresent RETURN(IfPresentKeyword);
405 import RETURN(ImportKeyword);
406 in RETURN(InParKeyword);
407 inconc RETURN(InconcKeyword);
408 infinity RETURN(InfinityKeyword);
409 inout RETURN(InOutParKeyword);
410 integer RETURN(IntegerKeyword);
411 interleave RETURN(InterleavedKeyword);
412 kill RETURN_DOT(KillKeyword);
413 killed RETURN_DOT(KilledKeyword);
414 label RETURN(LabelKeyword);
415 language RETURN(LanguageKeyword);
416 length RETURN(LengthKeyword);
417 log RETURN(LogKeyword);
418 map RETURN(MapKeyword);
419 match RETURN(MatchKeyword);
420 message RETURN(MessageKeyword);
421 mixed RETURN(MixedKeyword);
422 mod RETURN(ModKeyword);
423 modifies RETURN(ModifiesKeyword);
424 module RETURN(TTCN3ModuleKeyword);
425 modulepar RETURN(ModuleParKeyword);
426 mtc RETURN(MTCKeyword);
427 noblock RETURN(NoBlockKeyword);
428 none RETURN(NoneKeyword);
429 not RETURN(NotKeyword);
430 not_a_number RETURN(NaNKeyword);
431 not4b RETURN(Not4bKeyword);
432 nowait RETURN(NowaitKeyword);
433 null RETURN(NullKeyword);
434 objid RETURN(ObjectIdentifierKeyword);
435 octetstring RETURN(OctetStringKeyword);
436 of RETURN(OfKeyword);
437 omit RETURN(OmitKeyword);
438 on RETURN(OnKeyword);
439 optional RETURN(OptionalKeyword);
440 or RETURN(OrKeyword);
441 or4b RETURN(Or4bKeyword);
442 out RETURN(OutParKeyword);
443 override RETURN(OverrideKeyword);
444 param RETURN(ParamKeyword);
445 pass RETURN(PassKeyword);
446 pattern RETURN(PatternKeyword);
447 permutation RETURN(PermutationKeyword);
448 port RETURN(PortKeyword);
449 present RETURN(PresentKeyword);
450 private RETURN(PrivateKeyword);
451 procedure RETURN(ProcedureKeyword);
452 public RETURN(PublicKeyword);
453 raise RETURN_DOT(RaiseKeyword);
454 read RETURN_DOT(ReadKeyword);
455 receive RETURN_DOT(ReceiveOpKeyword);
456 record RETURN(RecordKeyword);
457 recursive RETURN(RecursiveKeyword);
458 refers RETURN(RefersKeyword);
459 rem RETURN(RemKeyword);
460 repeat RETURN(RepeatKeyword);
461 reply RETURN_DOT(ReplyKeyword);
462 return RETURN(ReturnKeyword);
463 running RETURN_DOT(RunningKeyword);
464 runs RETURN(RunsKeyword);
465 select RETURN(SelectKeyword);
466 self RETURN(SelfKeyword);
467 send RETURN_DOT(SendOpKeyword);
468 sender RETURN(SenderKeyword);
469 set RETURN(SetKeyword);
470 setverdict RETURN(SetVerdictKeyword);
471 signature RETURN(SignatureKeyword);
472 start RETURN_DOT(StartKeyword);
473 stop RETURN_DOT(StopKeyword);
474 subset RETURN(SubsetKeyword);
475 superset RETURN(SupersetKeyword);
476 system RETURN(SystemKeyword);
477 template RETURN(TemplateKeyword);
478 testcase RETURN(TestcaseKeyword);
479 timeout RETURN_DOT(TimeoutKeyword);
480 timer RETURN(TimerKeyword);
481 to RETURN(ToKeyword);
482 trigger RETURN_DOT(TriggerOpKeyword);
483 true RETURN(TrueKeyword);
484 type RETURN(TypeDefKeyword);
485 union RETURN(UnionKeyword);
486 universal RETURN(UniversalKeyword);
487 unmap RETURN(UnmapKeyword);
488 value RETURN(ValueKeyword);
489 valueof RETURN(ValueofKeyword);
490 var RETURN(VarKeyword);
491 variant RETURN(VariantKeyword);
492 verdicttype RETURN(VerdictTypeKeyword);
493 while RETURN(WhileKeyword);
494 with RETURN(WithKeyword);
495 xor RETURN(XorKeyword);
496 xor4b RETURN(Xor4bKeyword);
497
498 /* special TITAN specific keywords */
499
500 "@try" RETURN(TitanSpecificTryKeyword);
501 "@catch" RETURN(TitanSpecificCatchKeyword);
502 "@lazy" RETURN(TitanSpecificLazyKeyword);
503 "@profiler" RETURN(TitanSpecificProfilerKeyword);
504
505 /* Predefined function identifiers */
506
507 bit2hex RETURN(bit2hexKeyword);
508 bit2int RETURN(bit2intKeyword);
509 bit2oct RETURN(bit2octKeyword);
510 bit2str RETURN(bit2strKeyword);
511 char2int RETURN(char2intKeyword);
512 char2oct RETURN(char2octKeyword);
513 decomp RETURN(decompKeyword);
514 float2int RETURN(float2intKeyword);
515 float2str RETURN(float2strKeyword);
516 hex2bit RETURN(hex2bitKeyword);
517 hex2int RETURN(hex2intKeyword);
518 hex2oct RETURN(hex2octKeyword);
519 hex2str RETURN(hex2strKeyword);
520 int2bit RETURN(int2bitKeyword);
521 int2char RETURN(int2charKeyword);
522 int2enum RETURN(int2enumKeyword);
523 int2float RETURN(int2floatKeyword);
524 int2hex RETURN(int2hexKeyword);
525 int2oct RETURN(int2octKeyword);
526 int2str RETURN(int2strKeyword);
527 int2unichar RETURN(int2unicharKeyword);
528 isvalue RETURN(isvalueKeyword);
529 isbound RETURN(isboundKeyword);
530 ischosen RETURN(ischosenKeyword);
531 ispresent RETURN(ispresentKeyword);
532 lengthof RETURN(lengthofKeyword);
533 oct2bit RETURN(oct2bitKeyword);
534 oct2char RETURN(oct2charKeyword);
535 oct2hex RETURN(oct2hexKeyword);
536 oct2int RETURN(oct2intKeyword);
537 oct2str RETURN(oct2strKeyword);
538 regexp RETURN(regexpKeyword);
539 replace RETURN(replaceKeyword);
540 rnd RETURN(rndKeyword);
541 sizeof RETURN(sizeofKeyword);
542 str2bit RETURN(str2bitKeyword);
543 str2float RETURN(str2floatKeyword);
544 str2hex RETURN(str2hexKeyword);
545 str2int RETURN(str2intKeyword);
546 str2oct RETURN(str2octKeyword);
547 substr RETURN(substrKeyword);
548 unichar2int RETURN(unichar2intKeyword);
549 unichar2char RETURN(unichar2charKeyword);
550 log2str RETURN(log2strKeyword);
551 enum2int RETURN(enum2intKeyword);
552 encvalue RETURN(encvalueKeyword);
553 decvalue RETURN(decvalueKeyword);
554 testcasename RETURN(testcasenameKeyword);
555 ttcn2string RETURN(ttcn2stringKeyword);
556 string2ttcn RETURN(string2ttcnKeyword);
557 unichar2oct RETURN(unichar2octKeyword);
558 oct2unichar RETURN(oct2unicharKeyword);
559 remove_bom RETURN(remove_bomKeyWord);
560 get_stringencoding RETURN(get_stringencodingKeyWord);
561 encode_base64 RETURN(encode_base64KeyWord);
562 decode_base64 RETURN(decode_base64KeyWord);
563
564 /* Values */
565
566 {NUMBER} {
567 Location loc(infile, current_line, current_column, current_line,
568 current_column + yyleng);
569 yylval.int_val = new int_val_t(yytext, loc);
570 RETURN_LVAL(Number);
571 }
572
573 {FLOAT} {
574 Location loc(infile, current_line, current_column, current_line,
575 current_column + yyleng);
576 yylval.float_val = string2Real(yytext, loc);
577 RETURN_LVAL(FloatValue);
578 }
579
580 NULL RETURN(NullValue);
581
582 "'" {
583 binstr=memptystr();
584 valid_bit=true;
585 valid_oct=true;
586 half_oct=false;
587 contains_match=false;
588 contains_ws=false;
589 start_line = current_line;
590 start_column = current_column;
591 current_column++;
592 MD5_Update(&md5_ctx, yytext, yyleng);
593 BEGIN(SC_binstring);
594 }
595
596 \" {
597 yylval.str = memptystr();
598 start_line = current_line;
599 start_column = current_column;
600 current_column++;
601 MD5_Update(&md5_ctx, yytext, yyleng);
602 BEGIN(SC_cstring);
603 }
604
605 <SC_binstring> /* -------- SC_binstring scope -------------- */
606 {
607
608 {WHITESPACE}+ {
609 contains_ws = true;
610 current_column += yyleng;
611 }
612
613 {WHITESPACE}*{NEWLINE} {
614 contains_ws = true;
615 current_line++;
616 current_column = 0;
617 }
618
619 [01] {
620 binstr = mputc(binstr, yytext[0]);
621 half_oct = !half_oct;
622 current_column++;
623 }
624
625 [2-9A-F] {
626 binstr = mputc(binstr, yytext[0]);
627 valid_bit = false;
628 half_oct = !half_oct;
629 current_column++;
630 }
631
632 [a-f] {
633 binstr = mputc(binstr, yytext[0] - 'a' + 'A');
634 valid_bit = false;
635 half_oct = !half_oct;
636 current_column++;
637 }
638
639 "?"|"*" {
640 binstr = mputc(binstr, yytext[0]);
641 contains_match = true;
642 if (half_oct) valid_oct = false;
643 current_column++;
644 }
645
646 "'"[bBhHoO] {
647 yylloc.first_line = start_line;
648 yylloc.first_column = start_column;
649 yylloc.last_line = current_line;
650 yylloc.last_column = current_column + 2;
651 Location loc(infile, yylloc);
652 int ret_val = TOK_errval;
653 switch (yytext[1]) {
654 case 'b': {
655 Location loc2(infile, current_line, current_column + 1, current_line,
656 current_column + 2);
657 loc2.warning("The last character of a bitstring literal should be "
658 "`B' instead of `b'");
659 /* no break */ }
660 case 'B':
661 if (valid_bit) {
662 if (contains_ws) loc.warning("Bitstring %s contains whitespace and/or "
663 "newline character(s)", contains_match ? "match" : "value");
664 ret_val = contains_match ? BitStringMatch : Bstring;
665 yylval.string_val = new string(binstr);
666 } else loc.error("Bitstring value contains invalid character");
667 break;
668 case 'h': {
669 Location loc2(infile, current_line, current_column + 1, current_line,
670 current_column + 2);
671 loc2.warning("The last character of a hexstring literal should be "
672 "`H' instead of `h'");
673 /* no break */ }
674 case 'H':
675 if (contains_ws) loc.warning("Hexstring %s contains whitespace and/or "
676 "newline character(s)", contains_match ? "match" : "value");
677 ret_val = contains_match ? HexStringMatch : Hstring;
678 yylval.string_val = new string(binstr);
679 break;
680 case 'o': {
681 Location loc2(infile, current_line, current_column + 1, current_line,
682 current_column + 2);
683 loc2.warning("The last character of an octetstring literal should be "
684 "`O' instead of `o'");
685 /* no break */ }
686 case 'O':
687 if (valid_oct && !half_oct) {
688 if (contains_ws) loc.warning("Octetstring %s contains whitespace "
689 "and/or newline character(s)", contains_match ? "match" : "value");
690 ret_val = contains_match ? OctetStringMatch : Ostring;
691 yylval.string_val = new string(binstr);
692 } else if (contains_match) {
693 loc.error("Octetstring match contains half octet(s)");
694 } else {
695 loc.error("Octetstring value contains odd number of hexadecimal "
696 "digits");
697 }
698 }
699 MD5_Update(&md5_ctx, binstr, strlen(binstr));
700 Free(binstr);
701 update_md5();
702 BEGIN(INITIAL);
703 current_column += 2;
704 if (dot_flag) {
705 backup_token = ret_val;
706 backup_lval = yylval;
707 backup_lloc = yylloc;
708 RETURN_SAVED_DOT;
709 } else return ret_val;
710 }
711
712 "'" {
713 yylloc.first_line = start_line;
714 yylloc.first_column = start_column;
715 current_column++;
716 yylloc.last_line = current_line;
717 yylloc.last_column = current_column;
718 Location loc(infile, yylloc);
719 loc.error("Invalid binary string literal. Expecting `B', `H' or `O' after "
720 "the closing `''");
721 MD5_Update(&md5_ctx, binstr, strlen(binstr));
722 Free(binstr);
723 BEGIN(INITIAL);
724 RETURN_NOLOCUPD(TOK_errval);
725 }
726
727 . {
728 Location loc(infile, current_line, current_column, current_line,
729 current_column + 1);
730 int c = (unsigned char)yytext[0];
731 loc.error("Invalid character `%c' (0x%02X) in binary string",
732 isprint(c) ? c : '?', c);
733 MD5_Update(&md5_ctx, binstr, strlen(binstr));
734 Free(binstr);
735 MD5_Update(&md5_ctx, yytext, 1);
736 current_column++;
737 BEGIN(SC_binstring_bad);
738 }
739
740 } /* SC_binstring scope */
741
742 <SC_binstring_bad> /* -------- SC_binstring_bad scope -------------- */
743 {
744
745 {WHITESPACE}+ current_column += yyleng;
746
747 {WHITESPACE}*{NEWLINE} {
748 current_line++;
749 current_column = 0;
750 }
751
752 "'"[bBhHoO]? {
753 current_column += yyleng;
754 yylloc.first_line = start_line;
755 yylloc.first_column = start_column;
756 yylloc.last_line = current_line;
757 yylloc.last_column = current_column;
758 BEGIN(INITIAL);
759 RETURN_NOLOCUPD(TOK_errval);
760 }
761
762 . {
763 MD5_Update(&md5_ctx, yytext, yyleng);
764 current_column++;
765 }
766
767 } /* SC_binstring_bad scope */
768
769 <SC_cstring> /* -------- SC_cstring scope -------------- */
770 {
771
772 \\?{NEWLINE} { /* newline possibly preceded by backslash */
773 yylval.str = mputstr(yylval.str, yytext);
774 current_line++;
775 current_column = 0;
776 }
777
778 \"\"|\\. { /* two doublequotes or any backslash-escaped char */
779 yylval.str = mputstr(yylval.str, yytext);
780 current_column += 2;
781 /* Note that both get added ("external representation").
782 * parse_charstring_value() in charstring_la.l is responsible
783 * for transforming the string to "internal representation" */
784 }
785
786 \" {
787 current_column++;
788 yylloc.first_line = start_line;
789 yylloc.first_column = start_column;
790 yylloc.last_line = current_line;
791 yylloc.last_column = current_column;
792 MD5_Update(&md5_ctx, yylval.str, strlen(yylval.str));
793 update_md5();
794 BEGIN(INITIAL);
795 if (dot_flag) {
796 backup_token = Cstring;
797 backup_lval = yylval;
798 backup_lloc = yylloc;
799 RETURN_SAVED_DOT;
800 } else return Cstring;
801 }
802
803 . {
804 yylval.str = mputc(yylval.str, yytext[0]);
805 current_column++;
806 }
807
808 } /* SC_cstring scope */
809
810 /* Macros */
811
812 "%moduleId" {
813 yylval.macrotype = Value::MACRO_MODULEID;
814 RETURN_LVAL(MacroValue);
815 }
816 "%fileName" {
817 yylval.macrotype = Value::MACRO_FILENAME;
818 RETURN_LVAL(MacroValue);
819 }
820 "%lineNumber" {
821 yylval.macrotype = Value::MACRO_LINENUMBER;
822 RETURN_LVAL(MacroValue);
823 }
824 "%definitionId" {
825 yylval.macrotype = Value::MACRO_DEFINITIONID;
826 RETURN_LVAL(MacroValue);
827 }
828 "%testcaseId" {
829 yylval.macrotype = Value::MACRO_TESTCASEID;
830 RETURN_LVAL(MacroValue);
831 }
832 "%"{IDENTIFIER} {
833 fill_location();
834 Location loc(infile, yylloc);
835 loc.error("Invalid macro notation: `%s'", yytext);
836 RETURN_NOLOCUPD(TOK_errval);
837 }
838
839 "__MODULE__" {
840 yylval.macrotype = Value::MACRO_MODULEID;
841 RETURN_LVAL(MacroValue);
842 }
843 "__FILE__" {
844 yylval.macrotype = Value::MACRO_FILEPATH;
845 RETURN_LVAL(MacroValue);
846 }
847 "__BFILE__" {
848 yylval.macrotype = Value::MACRO_BFILENAME;
849 RETURN_LVAL(MacroValue);
850 }
851 "__LINE__" {
852 yylval.macrotype = Value::MACRO_LINENUMBER_C;
853 RETURN_LVAL(MacroValue);
854 }
855 "__SCOPE__" {
856 yylval.macrotype = Value::MACRO_SCOPE;
857 RETURN_LVAL(MacroValue);
858 }
859 "__TESTCASE__" {
860 yylval.macrotype = Value::MACRO_TESTCASEID;
861 RETURN_LVAL(MacroValue);
862 }
863 "__"{IDENTIFIER}"__" {
864 fill_location();
865 Location loc(infile, yylloc);
866 loc.error("Invalid macro notation: `%s'", yytext);
867 RETURN_NOLOCUPD(TOK_errval);
868 }
869
870 /* Multi-character operators */
871
872 ":=" RETURN(AssignmentChar);
873 "\.\." RETURN(DotDot);
874 "->" RETURN(PortRedirectSymbol);
875 "==" RETURN(EQ);
876 "!=" RETURN(NE);
877 ">=" RETURN(GE);
878 "<=" RETURN(LE);
879 "<<" RETURN(SL);
880 ">>" RETURN(SR);
881 "<@" RETURN(RL);
882 "@>" RETURN(_RR);
883
884 "++" |
885 "--" {
886 fill_location();
887 Location loc(infile, yylloc);
888 loc.error("Operator `%s' is reserved for future use", yytext);
889 }
890
891 /* Invalid operators */
892
893 "::=" {
894 fill_location();
895 Location loc(infile, yylloc);
896 loc.error("`::=' is not a valid assignment operator in TTCN-3. Did you mean "
897 "`:='?");
898 RETURN_NOLOCUPD(AssignmentChar);
899 }
900
901 "=" {
902 fill_location();
903 Location loc(infile, yylloc);
904 loc.error("A single `=' character cannot be used in TTCN-3. Did you mean "
905 "the assignment sign `:=' or the equality operator `=='?");
906 /* the former is more probable than the latter */
907 RETURN_NOLOCUPD(AssignmentChar);
908 }
909
910 "<>" {
911 fill_location();
912 Location loc(infile, yylloc);
913 loc.error("`<>' is not a valid comparison operator in TTCN-3. Did you mean "
914 "`!='?");
915 RETURN_NOLOCUPD(NE);
916 }
917
918 /* Identifiers */
919
920 {IDENTIFIER} {
921 yylval.id = new Identifier(Identifier::ID_TTCN, string(yyleng, yytext));
922 RETURN_LVAL(IDentifier);
923 }
924
925 /* Single character tokens (brackets, operators, etc.) */
926
927 \. {
928 update_md5();
929 if (dot_flag) {
930 /* store this dot in the backup */
931 backup_token = '.';
932 backup_lloc.first_line = current_line;
933 backup_lloc.first_column = current_column;
934 current_column++;
935 backup_lloc.last_line = current_line;
936 backup_lloc.last_column = current_column;
937 /* return the dot that was found previously */
938 RETURN_SAVED_DOT;
939 } else {
940 dot_flag = true;
941 dot_line = current_line;
942 dot_column = current_column;
943 current_column++;
944 }
945 }
946
947 [()\[\]{}+\-\*/&:;,<>\?!] RETURN(*yytext);
948
949 /* Invalid characters */
950
951 . {
952 fill_location();
953 Location loc(infile, yylloc);
954 int c = (unsigned char)yytext[0];
955 loc.error("Character `%c' (0x%02X) is not used in TTCN-3",
956 isprint(c) ? c : '?', c);
957 }
958
959 /* EOF rule */
960
961 <*><<EOF>> {
962 if (YY_START != INITIAL) {
963 Location loc(infile, start_line, start_column, current_line,
964 current_column);
965 switch (YY_START) {
966 case SC_blockcomment:
967 loc.error("Unterminated block comment");
968 break;
969 case SC_binstring:
970 Free(binstr);
971 /* no break */
972 case SC_binstring_bad:
973 loc.error("Unterminated binary string literal");
974 break;
975 case SC_cstring:
976 Free(yylval.str);
977 loc.error("Unterminated character string literal");
978 }
979 BEGIN(INITIAL);
980 }
981 if (dot_flag) {
982 dot_flag = false;
983 RETURN_SAVED_DOT;
984 } else {
985 yylloc.first_line = current_line;
986 yylloc.first_column = current_column;
987 yylloc.last_line = current_line;
988 yylloc.last_column = current_column + 1;
989 return EOF;
990 }
991 }
992
993 %%
994
995 void init_ttcn3_lex()
996 {
997 dot_flag = false;
998 current_line = 1;
999 current_column = 0;
1000 real_infile = infile;
1001 real_lineno_offset = 0;
1002 MD5_Init(&md5_ctx);
1003 }
1004
1005 void init_erroneous_lex(const char* p_infile, int p_line, int p_column)
1006 {
1007 infile = p_infile;
1008 current_line = p_line;
1009 current_column = p_column;
1010 real_infile = infile;
1011 real_lineno_offset = 0;
1012 dot_flag = false;
1013 }
1014
1015 void free_dot_flag_stuff()
1016 {
1017 if (dot_flag) {
1018 dot_flag = false;
1019 /* clean up the semantic value of the token that was backed up */
1020 switch (backup_token) {
1021 case IDentifier:
1022 delete backup_lval.id;
1023 break;
1024 case Bstring:
1025 case Hstring:
1026 case Ostring:
1027 case BitStringMatch:
1028 case HexStringMatch:
1029 case OctetStringMatch:
1030 delete backup_lval.string_val;
1031 break;
1032 case Cstring:
1033 Free(backup_lval.str);
1034 default:
1035 break;
1036 }
1037 }
1038 }
1039
1040 void free_ttcn3_lex()
1041 {
1042 free_dot_flag_stuff();
1043 fclose(ttcn3_in);
1044 ttcn3_lex_destroy();
1045 }
1046
1047 /* called from ttcn3_parse_file to finalize MD5 and add it to the module */
1048 void set_md5_checksum(Ttcn::Module *m)
1049 {
1050 unsigned char md5_sum[MD5_DIGEST_LENGTH];
1051 MD5_Final(md5_sum, &md5_ctx);
1052 m->set_checksum(sizeof(md5_sum), md5_sum);
1053 }
This page took 0.061458 seconds and 6 git commands to generate.