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
20 * Szabo, Janos Zoltan – initial implementation
21 * Zalanyi, Balazs Andor
23 ******************************************************************************/
25 %option never-interactive
29 /* Tokenizer for TTCN-3 Core Language */
31 #include "../../common/dbgnew.hh"
33 #include "../string.hh"
34 #include "../CompilerError.hh"
36 #include "../Value.hh"
37 #include "AST_ttcn3.hh"
38 #include "Ttcnstuff.hh" // at least for PortTypeBody::PortOperationMode_t
39 #include "Statement.hh" // for Statement::statementtype_t
40 #include "Attributes.hh"
44 #include <openssl/md5.h>
59 class IndexedTemplate;
60 class IndexedTemplates;
62 class CompTypeRefList;
65 using namespace Common;
68 #include "compiler.tab.hh"
70 #define yylval ttcn3_lval
71 #define yylloc ttcn3_lloc
73 /* global variable indicating the location of the returned token to bison */
74 extern YYLTYPE yylloc;
76 extern bool is_erroneous_parsed;
78 /* always points to the first character of the regexp to be recognized */
79 static int current_line, current_column;
81 /* when reporting an error in linemarker or preprocessor
82 * directive the real file name and line number is needed */
83 static const char* real_infile;
84 /* real_lineno = current_line + real_lineno_offset */
85 static int real_lineno_offset;
87 static bool dot_flag = false;
88 /* type of the backup token (that was found after a dot) */
89 static int backup_token;
90 /* semantic value of the backup token */
91 static YYSTYPE backup_lval;
92 /* location of the backup token */
93 static YYLTYPE backup_lloc;
95 static MD5_CTX md5_ctx;
97 static void fill_location()
99 yylloc.first_line = current_line;
100 yylloc.first_column = current_column;
101 current_column += yyleng;
102 yylloc.last_line = current_line;
103 yylloc.last_column = current_column;
106 static void update_md5()
108 MD5_Update(&md5_ctx, yytext, yyleng);
109 MD5_Update(&md5_ctx, " ", 1);
112 #define RETURN_SAVED_DOT \
115 yylloc.first_line = dot_line; \
116 yylloc.first_column = dot_column; \
117 yylloc.last_line = dot_line; \
118 yylloc.last_column = dot_column + 1; \
122 /* return macro for simple tokens without semantic value */
123 #define RETURN(ret_val) \
128 backup_token = ret_val; \
129 backup_lloc = yylloc; \
131 } else return ret_val; \
134 /* same as RETURN(ret_val) macro but without location update,
135 * usually a return after an error */
136 #define RETURN_NOLOCUPD(ret_val) \
140 backup_token = ret_val; \
141 backup_lloc = yylloc; \
143 } else return ret_val; \
146 /* return macro for simple tokens with semantic value */
147 #define RETURN_LVAL(ret_val) \
152 backup_token = ret_val; \
153 backup_lval = yylval; \
154 backup_lloc = yylloc; \
156 } else return ret_val; \
159 /* return macro for special tokens that are glued together with previous dot */
160 #define RETURN_DOT(ret_val) \
165 yylloc.first_line = dot_line; \
166 yylloc.first_column = dot_column; \
167 current_column += yyleng; \
168 yylloc.last_line = current_line; \
169 yylloc.last_column = current_column; \
170 return Dot##ret_val; \
177 extern string *parse_charstring_value(const char *str, const Location& loc);
181 NUMBER 0|([1-9][0-9]*)
183 FLOAT ({NUMBER}\.[0-9]+)|({NUMBER}(\.[0-9]+)?[Ee][+-]?{NUMBER})
185 IDENTIFIER [A-Za-z][A-Za-z0-9_]*
187 LINECOMMENT "//"[^\r\n]*
193 LINEMARKER {NUMBER}{WHITESPACE}+\"([^\\\"\r\n]|\\[^\r\n])*\"
195 TITAN "$#&&&(#TITANERRONEOUS$#&&^#% "
197 %x SC_blockcomment SC_cstring
198 %x SC_binstring SC_binstring_bad
201 /* local variables of yylex() */
202 int start_line = 0, start_column = 0; /**< used by block comments and
204 int dot_line = 0, dot_column = 0; /**< location of the previous '.' token */
205 /* variables used when processing binary strings */
206 expstring_t binstr = NULL; /**< the string itself */
207 bool valid_bit = false, /**< binstr is valid bitstring */
208 valid_oct = false, /**< binstr is valid octetstring */
209 half_oct = false, /**< binstr is not a valid octetstr but a valid hexstr */
210 contains_match = false, /**< binstr contains matching symbol */
211 contains_ws = false; /**< binstr contains whitespace characters */
214 if (backup_token == '.') {
215 /* Two dots were found in the previous call: the first one was returned,
216 * the second one is now in the backup. Let's assume that we have just
217 * found the second one. */
218 dot_line = backup_lloc.first_line;
219 dot_column = backup_lloc.first_column;
221 /* Return the token and its semantic value that was backed up after the
222 * last token (which was a dot). */
224 yylval = backup_lval;
225 yylloc = backup_lloc;
232 // hack: to avoid the erroneous parsing reporting a syntax error where it
233 // also lists TTCN3ModuleKeyword as a possible nonterminal to use
234 if (is_erroneous_parsed) {
235 RETURN(TitanErroneousHackKeyword);
237 Location loc(infile, current_line, current_column, current_line,
238 current_column + yyleng);
239 loc.error("Unexpected `%s'.", yytext);
243 /* Eat up comments and whitespaces */
246 start_line = current_line;
247 start_column = current_column;
249 BEGIN(SC_blockcomment);
252 <SC_blockcomment> /* -------- SC_blockcomment scope -------------- */
267 } /* SC_blockcomment */
269 {LINECOMMENT}?{NEWLINE} {
275 current_column += yyleng;
278 {WHITESPACE}+ current_column += yyleng;
280 /* C preprocessor line markers */
282 ^{WHITESPACE}*"#"({WHITESPACE}*"line")?{WHITESPACE}+{LINEMARKER}[^\r\n]*{NEWLINE} {
283 bool error_flag = false;
284 int real_lineno = current_line + real_lineno_offset;
285 /* skipping the leading whitespaces */
286 int marker_begin = 0;
287 while (yytext[marker_begin] != '#') marker_begin++;
288 /* skipping the trailing whitespaces and newline */
289 int marker_end = yyleng - 1;
290 while (yytext[marker_end] == '\r' || yytext[marker_end] == '\n' ||
291 yytext[marker_end] == ' ' || yytext[marker_end] == '\t') marker_end--;
293 Location loc(real_infile, real_lineno, current_column + marker_begin,
294 real_lineno, current_column + marker_end);
295 Error_Context cntxt(&loc, "In preprocessor line marker");
296 /* parsing out the line number */
297 int lineno_begin = marker_begin + 1;
298 while (!isdigit((unsigned char)yytext[lineno_begin])) lineno_begin++;
299 int lineno_end = lineno_begin + 1;
300 while (isdigit((int)yytext[lineno_end])) lineno_end++;
302 int new_lineno = strtol(yytext + lineno_begin, NULL, 10);
304 Location lineno_loc(real_infile, real_lineno, current_column + lineno_begin,
305 real_lineno, current_column + lineno_end);
306 string lineno_str(lineno_end - lineno_begin, yytext + lineno_begin);
307 lineno_loc.error("Line number `%s' is too large for being represented in "
308 "memory: %s", lineno_str.c_str(), strerror(errno));
311 /* parsing out the file name */
312 int filename_begin = lineno_end + 1;
313 while (yytext[filename_begin] != '"') filename_begin++;
315 int filename_end = filename_begin;
316 while (yytext[filename_end] != '"') {
317 if (yytext[filename_end] == '\\') filename_end += 2;
320 Location filename_loc(real_infile, real_lineno, current_column +
321 filename_begin - 1, real_lineno, current_column + filename_end + 1);
322 string filename_str(filename_end - filename_begin, yytext + filename_begin);
323 string *parsed_filename = parse_charstring_value(filename_str.c_str(),
325 if (!parsed_filename) error_flag = true;
326 /* updating the line/column counters */
328 /* the line marker is erroneous, use the real line numbers */
329 infile = real_infile;
330 current_line = real_lineno + 1;
331 real_lineno_offset = 0;
333 /* set the given line number */
334 infile = Location::add_source_file_name(*parsed_filename);
335 current_line = new_lineno;
336 real_lineno_offset = real_lineno + 1 - new_lineno;
339 delete parsed_filename;
342 ^{WHITESPACE}*"#"[^\r\n]* {
343 int real_lineno = current_line + real_lineno_offset;
344 /* skip the leading and trailing whitespaces */
345 int marker_begin = 0;
346 while (yytext[marker_begin] != '#') marker_begin++;
347 int marker_end = yyleng - 1;
348 while (yytext[marker_end] == ' ' || yytext[marker_end] == '\t') marker_end--;
350 Location loc(real_infile, real_lineno, current_column + marker_begin,
351 real_lineno, current_column + marker_end);
352 loc.error("Invalid/unsupported preprocessor directive or line marker: `%s'",
353 string(marker_end - marker_begin, yytext + marker_begin).c_str());
354 current_column += yyleng;
359 action RETURN(ActionKeyword);
360 activate RETURN(ActivateKeyword);
361 address RETURN(AddressKeyword);
362 alive RETURN_DOT(AliveKeyword);
363 all RETURN(AllKeyword);
364 alt RETURN(AltKeyword);
365 altstep RETURN(AltstepKeyword);
366 and RETURN(AndKeyword);
367 and4b RETURN(And4bKeyword);
368 any RETURN(AnyKeyword);
369 anytype RETURN(AnyTypeKeyword);
370 apply RETURN_DOT(ApplyKeyword);
371 bitstring RETURN(BitStringKeyword);
372 boolean RETURN(BooleanKeyword);
373 break RETURN(BreakKeyword);
374 call RETURN_DOT(CallOpKeyword);
375 case RETURN(CaseKeyword);
376 catch RETURN_DOT(CatchOpKeyword);
377 char RETURN(CharKeyword);
378 charstring RETURN(CharStringKeyword);
379 check RETURN_DOT(CheckOpKeyword);
380 clear RETURN_DOT(ClearOpKeyword);
381 complement RETURN(ComplementKeyword);
382 component RETURN(ComponentKeyword);
383 connect RETURN(ConnectKeyword);
384 const RETURN(ConstKeyword);
385 continue RETURN(ContinueKeyword);
386 control RETURN(ControlKeyword);
387 create RETURN_DOT(CreateKeyword);
388 deactivate RETURN(DeactivateKeyword);
389 default RETURN(DefaultKeyword);
390 derefers RETURN(DerefersKeyword);
391 disconnect RETURN(DisconnectKeyword);
392 display RETURN(DisplayKeyword);
393 do RETURN(DoKeyword);
394 done RETURN_DOT(DoneKeyword);
395 else RETURN(ElseKeyword);
396 encode RETURN(EncodeKeyword);
397 enumerated RETURN(EnumKeyword);
398 error RETURN(ErrorKeyword);
399 except RETURN(ExceptKeyword);
400 exception RETURN(ExceptionKeyword);
401 execute RETURN(ExecuteKeyword);
402 extends RETURN(ExtendsKeyword);
403 extension RETURN(ExtensionKeyword);
404 external RETURN(ExtKeyword);
405 fail RETURN(FailKeyword);
406 false RETURN(FalseKeyword);
407 float RETURN(FloatKeyword);
408 for RETURN(ForKeyword);
409 friend RETURN(FriendKeyword);
410 from RETURN(FromKeyword);
411 function RETURN(FunctionKeyword);
412 getcall RETURN_DOT(GetCallOpKeyword);
413 getreply RETURN_DOT(GetReplyOpKeyword);
414 getverdict RETURN(GetVerdictKeyword);
415 goto RETURN(GotoKeyword);
416 group RETURN(GroupKeyword);
417 halt RETURN_DOT(HaltKeyword);
418 hexstring RETURN(HexStringKeyword);
419 if RETURN(IfKeyword);
420 ifpresent RETURN(IfPresentKeyword);
421 import RETURN(ImportKeyword);
422 in RETURN(InParKeyword);
423 inconc RETURN(InconcKeyword);
424 infinity RETURN(InfinityKeyword);
425 inout RETURN(InOutParKeyword);
426 integer RETURN(IntegerKeyword);
427 interleave RETURN(InterleavedKeyword);
428 kill RETURN_DOT(KillKeyword);
429 killed RETURN_DOT(KilledKeyword);
430 label RETURN(LabelKeyword);
431 language RETURN(LanguageKeyword);
432 length RETURN(LengthKeyword);
433 log RETURN(LogKeyword);
434 map RETURN(MapKeyword);
435 match RETURN(MatchKeyword);
436 message RETURN(MessageKeyword);
437 mixed RETURN(MixedKeyword);
438 mod RETURN(ModKeyword);
439 modifies RETURN(ModifiesKeyword);
440 module RETURN(TTCN3ModuleKeyword);
441 modulepar RETURN(ModuleParKeyword);
442 mtc RETURN(MTCKeyword);
443 noblock RETURN(NoBlockKeyword);
444 none RETURN(NoneKeyword);
445 not RETURN(NotKeyword);
446 not_a_number RETURN(NaNKeyword);
447 not4b RETURN(Not4bKeyword);
448 nowait RETURN(NowaitKeyword);
449 null RETURN(NullKeyword);
450 objid RETURN(ObjectIdentifierKeyword);
451 octetstring RETURN(OctetStringKeyword);
452 of RETURN(OfKeyword);
453 omit RETURN(OmitKeyword);
454 on RETURN(OnKeyword);
455 optional RETURN(OptionalKeyword);
456 or RETURN(OrKeyword);
457 or4b RETURN(Or4bKeyword);
458 out RETURN(OutParKeyword);
459 override RETURN(OverrideKeyword);
460 param RETURN(ParamKeyword);
461 pass RETURN(PassKeyword);
462 pattern RETURN(PatternKeyword);
463 permutation RETURN(PermutationKeyword);
464 port RETURN(PortKeyword);
465 present RETURN(PresentKeyword);
466 private RETURN(PrivateKeyword);
467 procedure RETURN(ProcedureKeyword);
468 public RETURN(PublicKeyword);
469 raise RETURN_DOT(RaiseKeyword);
470 read RETURN_DOT(ReadKeyword);
471 receive RETURN_DOT(ReceiveOpKeyword);
472 record RETURN(RecordKeyword);
473 recursive RETURN(RecursiveKeyword);
474 refers RETURN(RefersKeyword);
475 rem RETURN(RemKeyword);
476 repeat RETURN(RepeatKeyword);
477 reply RETURN_DOT(ReplyKeyword);
478 return RETURN(ReturnKeyword);
479 running RETURN_DOT(RunningKeyword);
480 runs RETURN(RunsKeyword);
481 select RETURN(SelectKeyword);
482 self RETURN(SelfKeyword);
483 send RETURN_DOT(SendOpKeyword);
484 sender RETURN(SenderKeyword);
485 set RETURN(SetKeyword);
486 setverdict RETURN(SetVerdictKeyword);
487 signature RETURN(SignatureKeyword);
488 start RETURN_DOT(StartKeyword);
489 stop RETURN_DOT(StopKeyword);
490 subset RETURN(SubsetKeyword);
491 superset RETURN(SupersetKeyword);
492 system RETURN(SystemKeyword);
493 template RETURN(TemplateKeyword);
494 testcase RETURN(TestcaseKeyword);
495 timeout RETURN_DOT(TimeoutKeyword);
496 timer RETURN(TimerKeyword);
497 to RETURN(ToKeyword);
498 trigger RETURN_DOT(TriggerOpKeyword);
499 true RETURN(TrueKeyword);
500 type RETURN(TypeDefKeyword);
501 union RETURN(UnionKeyword);
502 universal RETURN(UniversalKeyword);
503 unmap RETURN(UnmapKeyword);
504 value RETURN(ValueKeyword);
505 valueof RETURN(ValueofKeyword);
506 var RETURN(VarKeyword);
507 variant RETURN(VariantKeyword);
508 verdicttype RETURN(VerdictTypeKeyword);
509 while RETURN(WhileKeyword);
510 with RETURN(WithKeyword);
511 xor RETURN(XorKeyword);
512 xor4b RETURN(Xor4bKeyword);
514 /* modifier keywords */
516 "@nocase" RETURN(NocaseKeyword);
517 "@lazy" RETURN(LazyKeyword);
519 /* special TITAN specific keywords */
521 "@try" RETURN(TitanSpecificTryKeyword);
522 "@catch" RETURN(TitanSpecificCatchKeyword);
523 "@profiler" RETURN(TitanSpecificProfilerKeyword);
526 /* Predefined function identifiers */
528 bit2hex RETURN(bit2hexKeyword);
529 bit2int RETURN(bit2intKeyword);
530 bit2oct RETURN(bit2octKeyword);
531 bit2str RETURN(bit2strKeyword);
532 char2int RETURN(char2intKeyword);
533 char2oct RETURN(char2octKeyword);
534 decomp RETURN(decompKeyword);
535 float2int RETURN(float2intKeyword);
536 float2str RETURN(float2strKeyword);
537 hex2bit RETURN(hex2bitKeyword);
538 hex2int RETURN(hex2intKeyword);
539 hex2oct RETURN(hex2octKeyword);
540 hex2str RETURN(hex2strKeyword);
541 int2bit RETURN(int2bitKeyword);
542 int2char RETURN(int2charKeyword);
543 int2enum RETURN(int2enumKeyword);
544 int2float RETURN(int2floatKeyword);
545 int2hex RETURN(int2hexKeyword);
546 int2oct RETURN(int2octKeyword);
547 int2str RETURN(int2strKeyword);
548 int2unichar RETURN(int2unicharKeyword);
549 isvalue RETURN(isvalueKeyword);
550 isbound RETURN(isboundKeyword);
551 ischosen RETURN(ischosenKeyword);
552 ispresent RETURN(ispresentKeyword);
553 lengthof RETURN(lengthofKeyword);
554 oct2bit RETURN(oct2bitKeyword);
555 oct2char RETURN(oct2charKeyword);
556 oct2hex RETURN(oct2hexKeyword);
557 oct2int RETURN(oct2intKeyword);
558 oct2str RETURN(oct2strKeyword);
559 regexp RETURN(regexpKeyword);
560 replace RETURN(replaceKeyword);
561 rnd RETURN(rndKeyword);
562 sizeof RETURN(sizeofKeyword);
563 str2bit RETURN(str2bitKeyword);
564 str2float RETURN(str2floatKeyword);
565 str2hex RETURN(str2hexKeyword);
566 str2int RETURN(str2intKeyword);
567 str2oct RETURN(str2octKeyword);
568 substr RETURN(substrKeyword);
569 unichar2int RETURN(unichar2intKeyword);
570 unichar2char RETURN(unichar2charKeyword);
571 log2str RETURN(log2strKeyword);
572 enum2int RETURN(enum2intKeyword);
573 encvalue RETURN(encvalueKeyword);
574 decvalue RETURN(decvalueKeyword);
575 testcasename RETURN(testcasenameKeyword);
576 ttcn2string RETURN(ttcn2stringKeyword);
577 string2ttcn RETURN(string2ttcnKeyword);
578 unichar2oct RETURN(unichar2octKeyword);
579 oct2unichar RETURN(oct2unicharKeyword);
580 remove_bom RETURN(remove_bomKeyWord);
581 get_stringencoding RETURN(get_stringencodingKeyWord);
582 encode_base64 RETURN(encode_base64KeyWord);
583 decode_base64 RETURN(decode_base64KeyWord);
588 Location loc(infile, current_line, current_column, current_line,
589 current_column + yyleng);
590 yylval.int_val = new int_val_t(yytext, loc);
595 Location loc(infile, current_line, current_column, current_line,
596 current_column + yyleng);
597 yylval.float_val = string2Real(yytext, loc);
598 RETURN_LVAL(FloatValue);
601 NULL RETURN(NullValue);
608 contains_match=false;
610 start_line = current_line;
611 start_column = current_column;
613 MD5_Update(&md5_ctx, yytext, yyleng);
618 yylval.str = memptystr();
619 start_line = current_line;
620 start_column = current_column;
622 MD5_Update(&md5_ctx, yytext, yyleng);
626 <SC_binstring> /* -------- SC_binstring scope -------------- */
631 current_column += yyleng;
634 {WHITESPACE}*{NEWLINE} {
641 binstr = mputc(binstr, yytext[0]);
642 half_oct = !half_oct;
647 binstr = mputc(binstr, yytext[0]);
649 half_oct = !half_oct;
654 binstr = mputc(binstr, yytext[0] - 'a' + 'A');
656 half_oct = !half_oct;
661 binstr = mputc(binstr, yytext[0]);
662 contains_match = true;
663 if (half_oct) valid_oct = false;
668 yylloc.first_line = start_line;
669 yylloc.first_column = start_column;
670 yylloc.last_line = current_line;
671 yylloc.last_column = current_column + 2;
672 Location loc(infile, yylloc);
673 int ret_val = TOK_errval;
676 Location loc2(infile, current_line, current_column + 1, current_line,
678 loc2.warning("The last character of a bitstring literal should be "
679 "`B' instead of `b'");
683 if (contains_ws) loc.warning("Bitstring %s contains whitespace and/or "
684 "newline character(s)", contains_match ? "match" : "value");
685 ret_val = contains_match ? BitStringMatch : Bstring;
686 yylval.string_val = new string(binstr);
687 } else loc.error("Bitstring value contains invalid character");
690 Location loc2(infile, current_line, current_column + 1, current_line,
692 loc2.warning("The last character of a hexstring literal should be "
693 "`H' instead of `h'");
696 if (contains_ws) loc.warning("Hexstring %s contains whitespace and/or "
697 "newline character(s)", contains_match ? "match" : "value");
698 ret_val = contains_match ? HexStringMatch : Hstring;
699 yylval.string_val = new string(binstr);
702 Location loc2(infile, current_line, current_column + 1, current_line,
704 loc2.warning("The last character of an octetstring literal should be "
705 "`O' instead of `o'");
708 if (valid_oct && !half_oct) {
709 if (contains_ws) loc.warning("Octetstring %s contains whitespace "
710 "and/or newline character(s)", contains_match ? "match" : "value");
711 ret_val = contains_match ? OctetStringMatch : Ostring;
712 yylval.string_val = new string(binstr);
713 } else if (contains_match) {
714 loc.error("Octetstring match contains half octet(s)");
716 loc.error("Octetstring value contains odd number of hexadecimal "
720 MD5_Update(&md5_ctx, binstr, strlen(binstr));
726 backup_token = ret_val;
727 backup_lval = yylval;
728 backup_lloc = yylloc;
730 } else return ret_val;
734 yylloc.first_line = start_line;
735 yylloc.first_column = start_column;
737 yylloc.last_line = current_line;
738 yylloc.last_column = current_column;
739 Location loc(infile, yylloc);
740 loc.error("Invalid binary string literal. Expecting `B', `H' or `O' after "
742 MD5_Update(&md5_ctx, binstr, strlen(binstr));
745 RETURN_NOLOCUPD(TOK_errval);
749 Location loc(infile, current_line, current_column, current_line,
751 int c = (unsigned char)yytext[0];
752 loc.error("Invalid character `%c' (0x%02X) in binary string",
753 isprint(c) ? c : '?', c);
754 MD5_Update(&md5_ctx, binstr, strlen(binstr));
756 MD5_Update(&md5_ctx, yytext, 1);
758 BEGIN(SC_binstring_bad);
761 } /* SC_binstring scope */
763 <SC_binstring_bad> /* -------- SC_binstring_bad scope -------------- */
766 {WHITESPACE}+ current_column += yyleng;
768 {WHITESPACE}*{NEWLINE} {
774 current_column += yyleng;
775 yylloc.first_line = start_line;
776 yylloc.first_column = start_column;
777 yylloc.last_line = current_line;
778 yylloc.last_column = current_column;
780 RETURN_NOLOCUPD(TOK_errval);
784 MD5_Update(&md5_ctx, yytext, yyleng);
788 } /* SC_binstring_bad scope */
790 <SC_cstring> /* -------- SC_cstring scope -------------- */
793 \\?{NEWLINE} { /* newline possibly preceded by backslash */
794 yylval.str = mputstr(yylval.str, yytext);
799 \"\"|\\. { /* two doublequotes or any backslash-escaped char */
800 yylval.str = mputstr(yylval.str, yytext);
802 /* Note that both get added ("external representation").
803 * parse_charstring_value() in charstring_la.l is responsible
804 * for transforming the string to "internal representation" */
809 yylloc.first_line = start_line;
810 yylloc.first_column = start_column;
811 yylloc.last_line = current_line;
812 yylloc.last_column = current_column;
813 MD5_Update(&md5_ctx, yylval.str, strlen(yylval.str));
817 backup_token = Cstring;
818 backup_lval = yylval;
819 backup_lloc = yylloc;
821 } else return Cstring;
825 yylval.str = mputc(yylval.str, yytext[0]);
829 } /* SC_cstring scope */
834 yylval.macrotype = Value::MACRO_MODULEID;
835 RETURN_LVAL(MacroValue);
838 yylval.macrotype = Value::MACRO_FILENAME;
839 RETURN_LVAL(MacroValue);
842 yylval.macrotype = Value::MACRO_LINENUMBER;
843 RETURN_LVAL(MacroValue);
846 yylval.macrotype = Value::MACRO_DEFINITIONID;
847 RETURN_LVAL(MacroValue);
850 yylval.macrotype = Value::MACRO_TESTCASEID;
851 RETURN_LVAL(MacroValue);
855 Location loc(infile, yylloc);
856 loc.error("Invalid macro notation: `%s'", yytext);
857 RETURN_NOLOCUPD(TOK_errval);
861 yylval.macrotype = Value::MACRO_MODULEID;
862 RETURN_LVAL(MacroValue);
865 yylval.macrotype = Value::MACRO_FILEPATH;
866 RETURN_LVAL(MacroValue);
869 yylval.macrotype = Value::MACRO_BFILENAME;
870 RETURN_LVAL(MacroValue);
873 yylval.macrotype = Value::MACRO_LINENUMBER_C;
874 RETURN_LVAL(MacroValue);
877 yylval.macrotype = Value::MACRO_SCOPE;
878 RETURN_LVAL(MacroValue);
881 yylval.macrotype = Value::MACRO_TESTCASEID;
882 RETURN_LVAL(MacroValue);
884 "__"{IDENTIFIER}"__" {
886 Location loc(infile, yylloc);
887 loc.error("Invalid macro notation: `%s'", yytext);
888 RETURN_NOLOCUPD(TOK_errval);
891 /* Multi-character operators */
893 ":=" RETURN(AssignmentChar);
894 "\.\." RETURN(DotDot);
895 "->" RETURN(PortRedirectSymbol);
908 Location loc(infile, yylloc);
909 loc.error("Operator `%s' is reserved for future use", yytext);
912 /* Invalid operators */
916 Location loc(infile, yylloc);
917 loc.error("`::=' is not a valid assignment operator in TTCN-3. Did you mean "
919 RETURN_NOLOCUPD(AssignmentChar);
924 Location loc(infile, yylloc);
925 loc.error("A single `=' character cannot be used in TTCN-3. Did you mean "
926 "the assignment sign `:=' or the equality operator `=='?");
927 /* the former is more probable than the latter */
928 RETURN_NOLOCUPD(AssignmentChar);
933 Location loc(infile, yylloc);
934 loc.error("`<>' is not a valid comparison operator in TTCN-3. Did you mean "
942 yylval.id = new Identifier(Identifier::ID_TTCN, string(yyleng, yytext));
943 RETURN_LVAL(IDentifier);
946 /* Single character tokens (brackets, operators, etc.) */
951 /* store this dot in the backup */
953 backup_lloc.first_line = current_line;
954 backup_lloc.first_column = current_column;
956 backup_lloc.last_line = current_line;
957 backup_lloc.last_column = current_column;
958 /* return the dot that was found previously */
962 dot_line = current_line;
963 dot_column = current_column;
968 [()\[\]{}+\-\*/&:;,<>\?!] RETURN(*yytext);
970 /* Invalid characters */
974 Location loc(infile, yylloc);
975 int c = (unsigned char)yytext[0];
976 loc.error("Character `%c' (0x%02X) is not used in TTCN-3",
977 isprint(c) ? c : '?', c);
983 if (YY_START != INITIAL) {
984 Location loc(infile, start_line, start_column, current_line,
987 case SC_blockcomment:
988 loc.error("Unterminated block comment");
993 case SC_binstring_bad:
994 loc.error("Unterminated binary string literal");
998 loc.error("Unterminated character string literal");
1006 yylloc.first_line = current_line;
1007 yylloc.first_column = current_column;
1008 yylloc.last_line = current_line;
1009 yylloc.last_column = current_column + 1;
1016 void init_ttcn3_lex()
1021 real_infile = infile;
1022 real_lineno_offset = 0;
1026 void init_erroneous_lex(const char* p_infile, int p_line, int p_column)
1029 current_line = p_line;
1030 current_column = p_column;
1031 real_infile = infile;
1032 real_lineno_offset = 0;
1036 void free_dot_flag_stuff()
1040 /* clean up the semantic value of the token that was backed up */
1041 switch (backup_token) {
1043 delete backup_lval.id;
1048 case BitStringMatch:
1049 case HexStringMatch:
1050 case OctetStringMatch:
1051 delete backup_lval.string_val;
1054 Free(backup_lval.str);
1061 void free_ttcn3_lex()
1063 free_dot_flag_stuff();
1065 ttcn3_lex_destroy();
1068 /* called from ttcn3_parse_file to finalize MD5 and add it to the module */
1069 void set_md5_checksum(Ttcn::Module *m)
1071 unsigned char md5_sum[MD5_DIGEST_LENGTH];
1072 MD5_Final(md5_sum, &md5_ctx);
1073 m->set_checksum(sizeof(md5_sum), md5_sum);