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
21 * Szabo, Janos Zoltan – initial implementation
22 * Zalanyi, Balazs Andor
24 ******************************************************************************/
26 %option never-interactive
30 /* Tokenizer for TTCN-3 Core Language */
32 #include "../../common/dbgnew.hh"
34 #include "../string.hh"
35 #include "../CompilerError.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"
45 #include <openssl/md5.h>
60 class IndexedTemplate;
61 class IndexedTemplates;
63 class CompTypeRefList;
66 using namespace Common;
69 #include "compiler.tab.hh"
71 #define yylval ttcn3_lval
72 #define yylloc ttcn3_lloc
74 /* global variable indicating the location of the returned token to bison */
75 extern YYLTYPE yylloc;
77 extern bool is_erroneous_parsed;
79 /* always points to the first character of the regexp to be recognized */
80 static int current_line, current_column;
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;
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;
96 static MD5_CTX md5_ctx;
98 static void fill_location()
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;
107 static void update_md5()
109 MD5_Update(&md5_ctx, yytext, yyleng);
110 MD5_Update(&md5_ctx, " ", 1);
113 #define RETURN_SAVED_DOT \
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; \
123 /* return macro for simple tokens without semantic value */
124 #define RETURN(ret_val) \
129 backup_token = ret_val; \
130 backup_lloc = yylloc; \
132 } else return ret_val; \
135 /* same as RETURN(ret_val) macro but without location update,
136 * usually a return after an error */
137 #define RETURN_NOLOCUPD(ret_val) \
141 backup_token = ret_val; \
142 backup_lloc = yylloc; \
144 } else return ret_val; \
147 /* return macro for simple tokens with semantic value */
148 #define RETURN_LVAL(ret_val) \
153 backup_token = ret_val; \
154 backup_lval = yylval; \
155 backup_lloc = yylloc; \
157 } else return ret_val; \
160 /* return macro for special tokens that are glued together with previous dot */
161 #define RETURN_DOT(ret_val) \
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; \
178 extern string *parse_charstring_value(const char *str, const Location& loc);
182 NUMBER 0|([1-9][0-9]*)
184 FLOAT ({NUMBER}\.[0-9]+)|({NUMBER}(\.[0-9]+)?[Ee][+-]?{NUMBER})
186 IDENTIFIER [A-Za-z][A-Za-z0-9_]*
188 LINECOMMENT "//"[^\r\n]*
194 LINEMARKER {NUMBER}{WHITESPACE}+\"([^\\\"\r\n]|\\[^\r\n])*\"
196 UID [uU][+]?[0-9A-Fa-f]{1,8}
198 TITAN "$#&&&(#TITANERRONEOUS$#&&^#% "
200 %x SC_blockcomment SC_cstring
201 %x SC_binstring SC_binstring_bad
205 /* local variables of yylex() */
206 int start_line = 0, start_column = 0; /**< used by block comments and
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 */
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;
225 /* Return the token and its semantic value that was backed up after the
226 * last token (which was a dot). */
228 yylval = backup_lval;
229 yylloc = backup_lloc;
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);
241 Location loc(infile, current_line, current_column, current_line,
242 current_column + yyleng);
243 loc.error("Unexpected `%s'.", yytext);
247 /* Eat up comments and whitespaces */
250 start_line = current_line;
251 start_column = current_column;
253 BEGIN(SC_blockcomment);
256 <SC_blockcomment> /* -------- SC_blockcomment scope -------------- */
271 } /* SC_blockcomment */
273 {LINECOMMENT}?{NEWLINE} {
279 current_column += yyleng;
282 {WHITESPACE}+ current_column += yyleng;
284 /* C preprocessor line markers */
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--;
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++;
306 int new_lineno = strtol(yytext + lineno_begin, NULL, 10);
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));
315 /* parsing out the file name */
316 int filename_begin = lineno_end + 1;
317 while (yytext[filename_begin] != '"') filename_begin++;
319 int filename_end = filename_begin;
320 while (yytext[filename_end] != '"') {
321 if (yytext[filename_end] == '\\') filename_end += 2;
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(),
329 if (!parsed_filename) error_flag = true;
330 /* updating the line/column counters */
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;
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;
343 delete parsed_filename;
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--;
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;
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 check RETURN_DOT(CheckOpKeyword);
384 clear RETURN_DOT(ClearOpKeyword);
385 complement RETURN(ComplementKeyword);
386 component RETURN(ComponentKeyword);
387 connect RETURN(ConnectKeyword);
388 const RETURN(ConstKeyword);
389 continue RETURN(ContinueKeyword);
390 control RETURN(ControlKeyword);
391 create RETURN_DOT(CreateKeyword);
392 deactivate RETURN(DeactivateKeyword);
393 default RETURN(DefaultKeyword);
394 derefers RETURN(DerefersKeyword);
395 disconnect RETURN(DisconnectKeyword);
396 display RETURN(DisplayKeyword);
397 do RETURN(DoKeyword);
398 done RETURN_DOT(DoneKeyword);
399 else RETURN(ElseKeyword);
400 encode RETURN(EncodeKeyword);
401 enumerated RETURN(EnumKeyword);
402 error RETURN(ErrorKeyword);
403 except RETURN(ExceptKeyword);
404 exception RETURN(ExceptionKeyword);
405 execute RETURN(ExecuteKeyword);
406 extends RETURN(ExtendsKeyword);
407 extension RETURN(ExtensionKeyword);
408 external RETURN(ExtKeyword);
409 fail RETURN(FailKeyword);
410 false RETURN(FalseKeyword);
411 float RETURN(FloatKeyword);
412 for RETURN(ForKeyword);
413 friend RETURN(FriendKeyword);
414 from RETURN(FromKeyword);
415 function RETURN(FunctionKeyword);
416 getcall RETURN_DOT(GetCallOpKeyword);
417 getreply RETURN_DOT(GetReplyOpKeyword);
418 getverdict RETURN(GetVerdictKeyword);
419 goto RETURN(GotoKeyword);
420 group RETURN(GroupKeyword);
421 halt RETURN_DOT(HaltKeyword);
422 hexstring RETURN(HexStringKeyword);
423 if RETURN(IfKeyword);
424 ifpresent RETURN(IfPresentKeyword);
425 import RETURN(ImportKeyword);
426 in RETURN(InParKeyword);
427 inconc RETURN(InconcKeyword);
428 infinity RETURN(InfinityKeyword);
429 inout RETURN(InOutParKeyword);
430 integer RETURN(IntegerKeyword);
431 interleave RETURN(InterleavedKeyword);
432 kill RETURN_DOT(KillKeyword);
433 killed RETURN_DOT(KilledKeyword);
434 label RETURN(LabelKeyword);
435 language RETURN(LanguageKeyword);
436 length RETURN(LengthKeyword);
437 log RETURN(LogKeyword);
438 map RETURN(MapKeyword);
439 match RETURN(MatchKeyword);
440 message RETURN(MessageKeyword);
441 mixed RETURN(MixedKeyword);
442 mod RETURN(ModKeyword);
443 modifies RETURN(ModifiesKeyword);
444 module RETURN(TTCN3ModuleKeyword);
445 modulepar RETURN(ModuleParKeyword);
446 mtc RETURN(MTCKeyword);
447 noblock RETURN(NoBlockKeyword);
448 none RETURN(NoneKeyword);
449 not RETURN(NotKeyword);
450 not_a_number RETURN(NaNKeyword);
451 not4b RETURN(Not4bKeyword);
452 nowait RETURN(NowaitKeyword);
453 null RETURN(NullKeyword);
454 objid RETURN(ObjectIdentifierKeyword);
455 octetstring RETURN(OctetStringKeyword);
456 of RETURN(OfKeyword);
457 omit RETURN(OmitKeyword);
458 on RETURN(OnKeyword);
459 optional RETURN(OptionalKeyword);
460 or RETURN(OrKeyword);
461 or4b RETURN(Or4bKeyword);
462 out RETURN(OutParKeyword);
463 override RETURN(OverrideKeyword);
464 param RETURN(ParamKeyword);
465 pass RETURN(PassKeyword);
466 pattern RETURN(PatternKeyword);
467 permutation RETURN(PermutationKeyword);
468 port RETURN(PortKeyword);
469 present RETURN(PresentKeyword);
470 private RETURN(PrivateKeyword);
471 procedure RETURN(ProcedureKeyword);
472 public RETURN(PublicKeyword);
473 raise RETURN_DOT(RaiseKeyword);
474 read RETURN_DOT(ReadKeyword);
475 receive RETURN_DOT(ReceiveOpKeyword);
476 record RETURN(RecordKeyword);
477 recursive RETURN(RecursiveKeyword);
478 refers RETURN(RefersKeyword);
479 rem RETURN(RemKeyword);
480 repeat RETURN(RepeatKeyword);
481 reply RETURN_DOT(ReplyKeyword);
482 return RETURN(ReturnKeyword);
483 running RETURN_DOT(RunningKeyword);
484 runs RETURN(RunsKeyword);
485 select RETURN(SelectKeyword);
486 self RETURN(SelfKeyword);
487 send RETURN_DOT(SendOpKeyword);
488 sender RETURN(SenderKeyword);
489 set RETURN(SetKeyword);
490 setverdict RETURN(SetVerdictKeyword);
491 signature RETURN(SignatureKeyword);
492 start RETURN_DOT(StartKeyword);
493 stop RETURN_DOT(StopKeyword);
494 subset RETURN(SubsetKeyword);
495 superset RETURN(SupersetKeyword);
496 system RETURN(SystemKeyword);
497 template RETURN(TemplateKeyword);
498 testcase RETURN(TestcaseKeyword);
499 timeout RETURN_DOT(TimeoutKeyword);
500 timer RETURN(TimerKeyword);
501 to RETURN(ToKeyword);
502 trigger RETURN_DOT(TriggerOpKeyword);
503 true RETURN(TrueKeyword);
504 type RETURN(TypeDefKeyword);
505 union RETURN(UnionKeyword);
506 universal RETURN(UniversalKeyword);
507 unmap RETURN(UnmapKeyword);
508 value RETURN(ValueKeyword);
509 valueof RETURN(ValueofKeyword);
510 var RETURN(VarKeyword);
511 variant RETURN(VariantKeyword);
512 verdicttype RETURN(VerdictTypeKeyword);
513 while RETURN(WhileKeyword);
514 with RETURN(WithKeyword);
515 xor RETURN(XorKeyword);
516 xor4b RETURN(Xor4bKeyword);
518 /* modifier keywords */
520 "@nocase" RETURN(NocaseKeyword);
521 "@lazy" RETURN(LazyKeyword);
523 /* special TITAN specific keywords */
525 "@try" RETURN(TitanSpecificTryKeyword);
526 "@catch" RETURN(TitanSpecificCatchKeyword);
527 "@profiler" RETURN(TitanSpecificProfilerKeyword);
530 /* Predefined function identifiers */
532 bit2hex RETURN(bit2hexKeyword);
533 bit2int RETURN(bit2intKeyword);
534 bit2oct RETURN(bit2octKeyword);
535 bit2str RETURN(bit2strKeyword);
536 char2int RETURN(char2intKeyword);
537 char2oct RETURN(char2octKeyword);
538 decomp RETURN(decompKeyword);
539 float2int RETURN(float2intKeyword);
540 float2str RETURN(float2strKeyword);
541 hex2bit RETURN(hex2bitKeyword);
542 hex2int RETURN(hex2intKeyword);
543 hex2oct RETURN(hex2octKeyword);
544 hex2str RETURN(hex2strKeyword);
545 int2bit RETURN(int2bitKeyword);
546 int2char RETURN(int2charKeyword);
547 int2enum RETURN(int2enumKeyword);
548 int2float RETURN(int2floatKeyword);
549 int2hex RETURN(int2hexKeyword);
550 int2oct RETURN(int2octKeyword);
551 int2str RETURN(int2strKeyword);
552 int2unichar RETURN(int2unicharKeyword);
553 isvalue RETURN(isvalueKeyword);
554 isbound RETURN(isboundKeyword);
555 ischosen RETURN(ischosenKeyword);
556 ispresent RETURN(ispresentKeyword);
557 lengthof RETURN(lengthofKeyword);
558 oct2bit RETURN(oct2bitKeyword);
559 oct2char RETURN(oct2charKeyword);
560 oct2hex RETURN(oct2hexKeyword);
561 oct2int RETURN(oct2intKeyword);
562 oct2str RETURN(oct2strKeyword);
563 regexp RETURN(regexpKeyword);
564 replace RETURN(replaceKeyword);
565 rnd RETURN(rndKeyword);
566 sizeof RETURN(sizeofKeyword);
567 str2bit RETURN(str2bitKeyword);
568 str2float RETURN(str2floatKeyword);
569 str2hex RETURN(str2hexKeyword);
570 str2int RETURN(str2intKeyword);
571 str2oct RETURN(str2octKeyword);
572 substr RETURN(substrKeyword);
573 unichar2int RETURN(unichar2intKeyword);
574 unichar2char RETURN(unichar2charKeyword);
575 log2str RETURN(log2strKeyword);
576 enum2int RETURN(enum2intKeyword);
577 encvalue RETURN(encvalueKeyword);
578 decvalue RETURN(decvalueKeyword);
579 testcasename RETURN(testcasenameKeyword);
580 ttcn2string RETURN(ttcn2stringKeyword);
581 string2ttcn RETURN(string2ttcnKeyword);
582 unichar2oct RETURN(unichar2octKeyword);
583 oct2unichar RETURN(oct2unicharKeyword);
584 remove_bom RETURN(remove_bomKeyWord);
585 get_stringencoding RETURN(get_stringencodingKeyWord);
586 encode_base64 RETURN(encode_base64KeyWord);
587 decode_base64 RETURN(decode_base64KeyWord);
588 encvalue_unichar RETURN(encvalue_unicharKeyWord);
589 decvalue_unichar RETURN(decvalue_unicharKeyWord);
590 any2unistr RETURN(any2unistrKeyWord);
595 Location loc(infile, current_line, current_column, current_line,
596 current_column + yyleng);
597 yylval.int_val = new int_val_t(yytext, loc);
602 Location loc(infile, current_line, current_column, current_line,
603 current_column + yyleng);
604 yylval.float_val = string2Real(yytext, loc);
605 RETURN_LVAL(FloatValue);
608 NULL RETURN(NullValue);
615 contains_match=false;
617 start_line = current_line;
618 start_column = current_column;
620 MD5_Update(&md5_ctx, yytext, yyleng);
625 yylval.str = memptystr();
626 start_line = current_line;
627 start_column = current_column;
629 MD5_Update(&md5_ctx, yytext, yyleng);
636 yylval.str = mcopystrn(yytext, yyleng);
637 RETURN_LVAL(Cstring);
640 [,] { RETURN(*yytext); }
642 [)] { BEGIN(INITIAL); RETURN(*yytext); }
645 <SC_binstring> /* -------- SC_binstring scope -------------- */
650 current_column += yyleng;
653 {WHITESPACE}*{NEWLINE} {
660 binstr = mputc(binstr, yytext[0]);
661 half_oct = !half_oct;
666 binstr = mputc(binstr, yytext[0]);
668 half_oct = !half_oct;
673 binstr = mputc(binstr, yytext[0] - 'a' + 'A');
675 half_oct = !half_oct;
680 binstr = mputc(binstr, yytext[0]);
681 contains_match = true;
682 if (half_oct) valid_oct = false;
687 yylloc.first_line = start_line;
688 yylloc.first_column = start_column;
689 yylloc.last_line = current_line;
690 yylloc.last_column = current_column + 2;
691 Location loc(infile, yylloc);
692 int ret_val = TOK_errval;
695 Location loc2(infile, current_line, current_column + 1, current_line,
697 loc2.warning("The last character of a bitstring literal should be "
698 "`B' instead of `b'");
702 if (contains_ws) loc.warning("Bitstring %s contains whitespace and/or "
703 "newline character(s)", contains_match ? "match" : "value");
704 ret_val = contains_match ? BitStringMatch : Bstring;
705 yylval.string_val = new string(binstr);
706 } else loc.error("Bitstring value contains invalid character");
709 Location loc2(infile, current_line, current_column + 1, current_line,
711 loc2.warning("The last character of a hexstring literal should be "
712 "`H' instead of `h'");
715 if (contains_ws) loc.warning("Hexstring %s contains whitespace and/or "
716 "newline character(s)", contains_match ? "match" : "value");
717 ret_val = contains_match ? HexStringMatch : Hstring;
718 yylval.string_val = new string(binstr);
721 Location loc2(infile, current_line, current_column + 1, current_line,
723 loc2.warning("The last character of an octetstring literal should be "
724 "`O' instead of `o'");
727 if (valid_oct && !half_oct) {
728 if (contains_ws) loc.warning("Octetstring %s contains whitespace "
729 "and/or newline character(s)", contains_match ? "match" : "value");
730 ret_val = contains_match ? OctetStringMatch : Ostring;
731 yylval.string_val = new string(binstr);
732 } else if (contains_match) {
733 loc.error("Octetstring match contains half octet(s)");
735 loc.error("Octetstring value contains odd number of hexadecimal "
739 MD5_Update(&md5_ctx, binstr, strlen(binstr));
745 backup_token = ret_val;
746 backup_lval = yylval;
747 backup_lloc = yylloc;
749 } else return ret_val;
753 yylloc.first_line = start_line;
754 yylloc.first_column = start_column;
756 yylloc.last_line = current_line;
757 yylloc.last_column = current_column;
758 Location loc(infile, yylloc);
759 loc.error("Invalid binary string literal. Expecting `B', `H' or `O' after "
761 MD5_Update(&md5_ctx, binstr, strlen(binstr));
764 RETURN_NOLOCUPD(TOK_errval);
768 Location loc(infile, current_line, current_column, current_line,
770 int c = (unsigned char)yytext[0];
771 loc.error("Invalid character `%c' (0x%02X) in binary string",
772 isprint(c) ? c : '?', c);
773 MD5_Update(&md5_ctx, binstr, strlen(binstr));
775 MD5_Update(&md5_ctx, yytext, 1);
777 BEGIN(SC_binstring_bad);
780 } /* SC_binstring scope */
782 <SC_binstring_bad> /* -------- SC_binstring_bad scope -------------- */
785 {WHITESPACE}+ current_column += yyleng;
787 {WHITESPACE}*{NEWLINE} {
793 current_column += yyleng;
794 yylloc.first_line = start_line;
795 yylloc.first_column = start_column;
796 yylloc.last_line = current_line;
797 yylloc.last_column = current_column;
799 RETURN_NOLOCUPD(TOK_errval);
803 MD5_Update(&md5_ctx, yytext, yyleng);
807 } /* SC_binstring_bad scope */
809 <SC_cstring> /* -------- SC_cstring scope -------------- */
812 \\?{NEWLINE} { /* newline possibly preceded by backslash */
813 yylval.str = mputstr(yylval.str, yytext);
818 \"\"|\\. { /* two doublequotes or any backslash-escaped char */
819 yylval.str = mputstr(yylval.str, yytext);
821 /* Note that both get added ("external representation").
822 * parse_charstring_value() in charstring_la.l is responsible
823 * for transforming the string to "internal representation" */
828 yylloc.first_line = start_line;
829 yylloc.first_column = start_column;
830 yylloc.last_line = current_line;
831 yylloc.last_column = current_column;
832 MD5_Update(&md5_ctx, yylval.str, strlen(yylval.str));
836 backup_token = Cstring;
837 backup_lval = yylval;
838 backup_lloc = yylloc;
840 } else return Cstring;
844 yylval.str = mputc(yylval.str, yytext[0]);
848 } /* SC_cstring scope */
853 yylval.macrotype = Value::MACRO_MODULEID;
854 RETURN_LVAL(MacroValue);
857 yylval.macrotype = Value::MACRO_FILENAME;
858 RETURN_LVAL(MacroValue);
861 yylval.macrotype = Value::MACRO_LINENUMBER;
862 RETURN_LVAL(MacroValue);
865 yylval.macrotype = Value::MACRO_DEFINITIONID;
866 RETURN_LVAL(MacroValue);
869 yylval.macrotype = Value::MACRO_TESTCASEID;
870 RETURN_LVAL(MacroValue);
874 Location loc(infile, yylloc);
875 loc.error("Invalid macro notation: `%s'", yytext);
876 RETURN_NOLOCUPD(TOK_errval);
880 yylval.macrotype = Value::MACRO_MODULEID;
881 RETURN_LVAL(MacroValue);
884 yylval.macrotype = Value::MACRO_FILEPATH;
885 RETURN_LVAL(MacroValue);
888 yylval.macrotype = Value::MACRO_BFILENAME;
889 RETURN_LVAL(MacroValue);
892 yylval.macrotype = Value::MACRO_LINENUMBER_C;
893 RETURN_LVAL(MacroValue);
896 yylval.macrotype = Value::MACRO_SCOPE;
897 RETURN_LVAL(MacroValue);
900 yylval.macrotype = Value::MACRO_TESTCASEID;
901 RETURN_LVAL(MacroValue);
903 "__"{IDENTIFIER}"__" {
905 Location loc(infile, yylloc);
906 loc.error("Invalid macro notation: `%s'", yytext);
907 RETURN_NOLOCUPD(TOK_errval);
910 /* Multi-character operators */
912 ":=" RETURN(AssignmentChar);
913 "\.\." RETURN(DotDot);
914 "->" RETURN(PortRedirectSymbol);
927 Location loc(infile, yylloc);
928 loc.error("Operator `%s' is reserved for future use", yytext);
931 /* Invalid operators */
935 Location loc(infile, yylloc);
936 loc.error("`::=' is not a valid assignment operator in TTCN-3. Did you mean "
938 RETURN_NOLOCUPD(AssignmentChar);
943 Location loc(infile, yylloc);
944 loc.error("A single `=' character cannot be used in TTCN-3. Did you mean "
945 "the assignment sign `:=' or the equality operator `=='?");
946 /* the former is more probable than the latter */
947 RETURN_NOLOCUPD(AssignmentChar);
952 Location loc(infile, yylloc);
953 loc.error("`<>' is not a valid comparison operator in TTCN-3. Did you mean "
961 yylval.id = new Identifier(Identifier::ID_TTCN, string(yyleng, yytext));
962 RETURN_LVAL(IDentifier);
965 /* Single character tokens (brackets, operators, etc.) */
970 /* store this dot in the backup */
972 backup_lloc.first_line = current_line;
973 backup_lloc.first_column = current_column;
975 backup_lloc.last_line = current_line;
976 backup_lloc.last_column = current_column;
977 /* return the dot that was found previously */
981 dot_line = current_line;
982 dot_column = current_column;
987 [()\[\]{}+\-\*/&:;,<>\?!] RETURN(*yytext);
989 /* Invalid characters */
993 Location loc(infile, yylloc);
994 int c = (unsigned char)yytext[0];
995 loc.error("Character `%c' (0x%02X) is not used in TTCN-3",
996 isprint(c) ? c : '?', c);
1002 if (YY_START != INITIAL) {
1003 Location loc(infile, start_line, start_column, current_line,
1006 case SC_blockcomment:
1007 loc.error("Unterminated block comment");
1012 case SC_binstring_bad:
1013 loc.error("Unterminated binary string literal");
1017 loc.error("Unterminated character string literal");
1025 yylloc.first_line = current_line;
1026 yylloc.first_column = current_column;
1027 yylloc.last_line = current_line;
1028 yylloc.last_column = current_column + 1;
1035 void init_ttcn3_lex()
1040 real_infile = infile;
1041 real_lineno_offset = 0;
1045 void init_erroneous_lex(const char* p_infile, int p_line, int p_column)
1048 current_line = p_line;
1049 current_column = p_column;
1050 real_infile = infile;
1051 real_lineno_offset = 0;
1055 void free_dot_flag_stuff()
1059 /* clean up the semantic value of the token that was backed up */
1060 switch (backup_token) {
1062 delete backup_lval.id;
1067 case BitStringMatch:
1068 case HexStringMatch:
1069 case OctetStringMatch:
1070 delete backup_lval.string_val;
1073 Free(backup_lval.str);
1080 void free_ttcn3_lex()
1082 free_dot_flag_stuff();
1084 ttcn3_lex_destroy();
1087 /* called from ttcn3_parse_file to finalize MD5 and add it to the module */
1088 void set_md5_checksum(Ttcn::Module *m)
1090 unsigned char md5_sum[MD5_DIGEST_LENGTH];
1091 MD5_Final(md5_sum, &md5_ctx);
1092 m->set_checksum(sizeof(md5_sum), md5_sum);