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