Sync with 5.4.3
[deliverable/titan.core.git] / compiler2 / ttcn3 / compiler.l
CommitLineData
970ed795 1/******************************************************************************
3abe9331 2 * Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
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
30namespace Common {
31 class IndexedValue;
32 class Location;
33}
34
35namespace 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
49using namespace Common;
50using 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 */
58extern YYLTYPE yylloc;
59
60extern bool is_erroneous_parsed;
61
62/* always points to the first character of the regexp to be recognized */
63static 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 */
67static const char* real_infile;
68/* real_lineno = current_line + real_lineno_offset */
69static int real_lineno_offset;
70
71static bool dot_flag = false;
72/* type of the backup token (that was found after a dot) */
73static int backup_token;
74/* semantic value of the backup token */
75static YYSTYPE backup_lval;
76/* location of the backup token */
77static YYLTYPE backup_lloc;
78
79static MD5_CTX md5_ctx;
80
81static 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
90static 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
161extern string *parse_charstring_value(const char *str, const Location& loc);
162
163%}
164
165NUMBER 0|([1-9][0-9]*)
166
167FLOAT ({NUMBER}\.[0-9]+)|({NUMBER}(\.[0-9]+)?[Ee][+-]?{NUMBER})
168
169IDENTIFIER [A-Za-z][A-Za-z0-9_]*
170
171LINECOMMENT "//"[^\r\n]*
172
173WHITESPACE [ \t\v\f]
174
175NEWLINE \r|\n|\r\n
176
177LINEMARKER {NUMBER}{WHITESPACE}+\"([^\\\"\r\n]|\\[^\r\n])*\"
178
179TITAN "$#&&&(#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} {
970ed795
EL
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
343action RETURN(ActionKeyword);
344activate RETURN(ActivateKeyword);
345address RETURN(AddressKeyword);
346alive RETURN_DOT(AliveKeyword);
347all RETURN(AllKeyword);
348alt RETURN(AltKeyword);
349altstep RETURN(AltstepKeyword);
350and RETURN(AndKeyword);
351and4b RETURN(And4bKeyword);
352any RETURN(AnyKeyword);
353anytype RETURN(AnyTypeKeyword);
354apply RETURN_DOT(ApplyKeyword);
355bitstring RETURN(BitStringKeyword);
356boolean RETURN(BooleanKeyword);
357break RETURN(BreakKeyword);
358call RETURN_DOT(CallOpKeyword);
359case RETURN(CaseKeyword);
360catch RETURN_DOT(CatchOpKeyword);
361char RETURN(CharKeyword);
362charstring RETURN(CharStringKeyword);
363check RETURN_DOT(CheckOpKeyword);
364clear RETURN_DOT(ClearOpKeyword);
365complement RETURN(ComplementKeyword);
366component RETURN(ComponentKeyword);
367connect RETURN(ConnectKeyword);
368const RETURN(ConstKeyword);
369continue RETURN(ContinueKeyword);
370control RETURN(ControlKeyword);
371create RETURN_DOT(CreateKeyword);
372deactivate RETURN(DeactivateKeyword);
373default RETURN(DefaultKeyword);
374derefers RETURN(DerefersKeyword);
375disconnect RETURN(DisconnectKeyword);
376display RETURN(DisplayKeyword);
377do RETURN(DoKeyword);
378done RETURN_DOT(DoneKeyword);
379else RETURN(ElseKeyword);
380encode RETURN(EncodeKeyword);
381enumerated RETURN(EnumKeyword);
382error RETURN(ErrorKeyword);
383except RETURN(ExceptKeyword);
384exception RETURN(ExceptionKeyword);
385execute RETURN(ExecuteKeyword);
386extends RETURN(ExtendsKeyword);
387extension RETURN(ExtensionKeyword);
388external RETURN(ExtKeyword);
389fail RETURN(FailKeyword);
390false RETURN(FalseKeyword);
391float RETURN(FloatKeyword);
392for RETURN(ForKeyword);
393friend RETURN(FriendKeyword);
394from RETURN(FromKeyword);
395function RETURN(FunctionKeyword);
396getcall RETURN_DOT(GetCallOpKeyword);
397getreply RETURN_DOT(GetReplyOpKeyword);
398getverdict RETURN(GetVerdictKeyword);
399goto RETURN(GotoKeyword);
400group RETURN(GroupKeyword);
401halt RETURN_DOT(HaltKeyword);
402hexstring RETURN(HexStringKeyword);
403if RETURN(IfKeyword);
404ifpresent RETURN(IfPresentKeyword);
405import RETURN(ImportKeyword);
406in RETURN(InParKeyword);
407inconc RETURN(InconcKeyword);
408infinity RETURN(InfinityKeyword);
409inout RETURN(InOutParKeyword);
410integer RETURN(IntegerKeyword);
411interleave RETURN(InterleavedKeyword);
412kill RETURN_DOT(KillKeyword);
413killed RETURN_DOT(KilledKeyword);
414label RETURN(LabelKeyword);
415language RETURN(LanguageKeyword);
416length RETURN(LengthKeyword);
417log RETURN(LogKeyword);
418map RETURN(MapKeyword);
419match RETURN(MatchKeyword);
420message RETURN(MessageKeyword);
421mixed RETURN(MixedKeyword);
422mod RETURN(ModKeyword);
423modifies RETURN(ModifiesKeyword);
424module RETURN(TTCN3ModuleKeyword);
425modulepar RETURN(ModuleParKeyword);
426mtc RETURN(MTCKeyword);
427noblock RETURN(NoBlockKeyword);
428none RETURN(NoneKeyword);
429not RETURN(NotKeyword);
430not_a_number RETURN(NaNKeyword);
431not4b RETURN(Not4bKeyword);
432nowait RETURN(NowaitKeyword);
433null RETURN(NullKeyword);
434objid RETURN(ObjectIdentifierKeyword);
435octetstring RETURN(OctetStringKeyword);
436of RETURN(OfKeyword);
437omit RETURN(OmitKeyword);
438on RETURN(OnKeyword);
439optional RETURN(OptionalKeyword);
440or RETURN(OrKeyword);
441or4b RETURN(Or4bKeyword);
442out RETURN(OutParKeyword);
443override RETURN(OverrideKeyword);
444param RETURN(ParamKeyword);
445pass RETURN(PassKeyword);
446pattern RETURN(PatternKeyword);
447permutation RETURN(PermutationKeyword);
448port RETURN(PortKeyword);
449present RETURN(PresentKeyword);
450private RETURN(PrivateKeyword);
451procedure RETURN(ProcedureKeyword);
452public RETURN(PublicKeyword);
453raise RETURN_DOT(RaiseKeyword);
454read RETURN_DOT(ReadKeyword);
455receive RETURN_DOT(ReceiveOpKeyword);
456record RETURN(RecordKeyword);
457recursive RETURN(RecursiveKeyword);
458refers RETURN(RefersKeyword);
459rem RETURN(RemKeyword);
460repeat RETURN(RepeatKeyword);
461reply RETURN_DOT(ReplyKeyword);
462return RETURN(ReturnKeyword);
463running RETURN_DOT(RunningKeyword);
464runs RETURN(RunsKeyword);
465select RETURN(SelectKeyword);
466self RETURN(SelfKeyword);
467send RETURN_DOT(SendOpKeyword);
468sender RETURN(SenderKeyword);
469set RETURN(SetKeyword);
470setverdict RETURN(SetVerdictKeyword);
471signature RETURN(SignatureKeyword);
472start RETURN_DOT(StartKeyword);
473stop RETURN_DOT(StopKeyword);
474subset RETURN(SubsetKeyword);
475superset RETURN(SupersetKeyword);
476system RETURN(SystemKeyword);
477template RETURN(TemplateKeyword);
478testcase RETURN(TestcaseKeyword);
479timeout RETURN_DOT(TimeoutKeyword);
480timer RETURN(TimerKeyword);
481to RETURN(ToKeyword);
482trigger RETURN_DOT(TriggerOpKeyword);
483true RETURN(TrueKeyword);
484type RETURN(TypeDefKeyword);
485union RETURN(UnionKeyword);
486universal RETURN(UniversalKeyword);
487unmap RETURN(UnmapKeyword);
488value RETURN(ValueKeyword);
489valueof RETURN(ValueofKeyword);
490var RETURN(VarKeyword);
491variant RETURN(VariantKeyword);
492verdicttype RETURN(VerdictTypeKeyword);
493while RETURN(WhileKeyword);
494with RETURN(WithKeyword);
495xor RETURN(XorKeyword);
496xor4b RETURN(Xor4bKeyword);
497
feade998 498 /* modifier keywords */
499
500"@nocase" RETURN(NocaseKeyword);
501"@lazy" RETURN(LazyKeyword);
502
970ed795
EL
503 /* special TITAN specific keywords */
504
505"@try" RETURN(TitanSpecificTryKeyword);
506"@catch" RETURN(TitanSpecificCatchKeyword);
a38c6d4c 507"@profiler" RETURN(TitanSpecificProfilerKeyword);
970ed795 508
feade998 509
970ed795
EL
510 /* Predefined function identifiers */
511
512bit2hex RETURN(bit2hexKeyword);
513bit2int RETURN(bit2intKeyword);
514bit2oct RETURN(bit2octKeyword);
515bit2str RETURN(bit2strKeyword);
516char2int RETURN(char2intKeyword);
517char2oct RETURN(char2octKeyword);
518decomp RETURN(decompKeyword);
519float2int RETURN(float2intKeyword);
520float2str RETURN(float2strKeyword);
521hex2bit RETURN(hex2bitKeyword);
522hex2int RETURN(hex2intKeyword);
523hex2oct RETURN(hex2octKeyword);
524hex2str RETURN(hex2strKeyword);
525int2bit RETURN(int2bitKeyword);
526int2char RETURN(int2charKeyword);
3abe9331 527int2enum RETURN(int2enumKeyword);
970ed795
EL
528int2float RETURN(int2floatKeyword);
529int2hex RETURN(int2hexKeyword);
530int2oct RETURN(int2octKeyword);
531int2str RETURN(int2strKeyword);
532int2unichar RETURN(int2unicharKeyword);
533isvalue RETURN(isvalueKeyword);
534isbound RETURN(isboundKeyword);
535ischosen RETURN(ischosenKeyword);
536ispresent RETURN(ispresentKeyword);
537lengthof RETURN(lengthofKeyword);
538oct2bit RETURN(oct2bitKeyword);
539oct2char RETURN(oct2charKeyword);
540oct2hex RETURN(oct2hexKeyword);
541oct2int RETURN(oct2intKeyword);
542oct2str RETURN(oct2strKeyword);
543regexp RETURN(regexpKeyword);
544replace RETURN(replaceKeyword);
545rnd RETURN(rndKeyword);
546sizeof RETURN(sizeofKeyword);
547str2bit RETURN(str2bitKeyword);
548str2float RETURN(str2floatKeyword);
549str2hex RETURN(str2hexKeyword);
550str2int RETURN(str2intKeyword);
551str2oct RETURN(str2octKeyword);
552substr RETURN(substrKeyword);
553unichar2int RETURN(unichar2intKeyword);
554unichar2char RETURN(unichar2charKeyword);
555log2str RETURN(log2strKeyword);
556enum2int RETURN(enum2intKeyword);
557encvalue RETURN(encvalueKeyword);
558decvalue RETURN(decvalueKeyword);
559testcasename RETURN(testcasenameKeyword);
560ttcn2string RETURN(ttcn2stringKeyword);
561string2ttcn RETURN(string2ttcnKeyword);
562unichar2oct RETURN(unichar2octKeyword);
563oct2unichar RETURN(oct2unicharKeyword);
564remove_bom RETURN(remove_bomKeyWord);
565get_stringencoding RETURN(get_stringencodingKeyWord);
566encode_base64 RETURN(encode_base64KeyWord);
567decode_base64 RETURN(decode_base64KeyWord);
568
569 /* Values */
570
571{NUMBER} {
572 Location loc(infile, current_line, current_column, current_line,
573 current_column + yyleng);
574 yylval.int_val = new int_val_t(yytext, loc);
575 RETURN_LVAL(Number);
576}
577
578{FLOAT} {
579 Location loc(infile, current_line, current_column, current_line,
580 current_column + yyleng);
581 yylval.float_val = string2Real(yytext, loc);
582 RETURN_LVAL(FloatValue);
583}
584
585NULL RETURN(NullValue);
586
587"'" {
588 binstr=memptystr();
589 valid_bit=true;
590 valid_oct=true;
591 half_oct=false;
592 contains_match=false;
593 contains_ws=false;
594 start_line = current_line;
595 start_column = current_column;
596 current_column++;
597 MD5_Update(&md5_ctx, yytext, yyleng);
598 BEGIN(SC_binstring);
599}
600
601\" {
602 yylval.str = memptystr();
603 start_line = current_line;
604 start_column = current_column;
605 current_column++;
606 MD5_Update(&md5_ctx, yytext, yyleng);
607 BEGIN(SC_cstring);
608}
609
610<SC_binstring> /* -------- SC_binstring scope -------------- */
611{
612
613 {WHITESPACE}+ {
614 contains_ws = true;
615 current_column += yyleng;
616 }
617
618 {WHITESPACE}*{NEWLINE} {
619 contains_ws = true;
620 current_line++;
621 current_column = 0;
622 }
623
624 [01] {
625 binstr = mputc(binstr, yytext[0]);
626 half_oct = !half_oct;
627 current_column++;
628 }
629
630 [2-9A-F] {
631 binstr = mputc(binstr, yytext[0]);
632 valid_bit = false;
633 half_oct = !half_oct;
634 current_column++;
635 }
636
637 [a-f] {
638 binstr = mputc(binstr, yytext[0] - 'a' + 'A');
639 valid_bit = false;
640 half_oct = !half_oct;
641 current_column++;
642 }
643
644 "?"|"*" {
645 binstr = mputc(binstr, yytext[0]);
646 contains_match = true;
647 if (half_oct) valid_oct = false;
648 current_column++;
649 }
650
651 "'"[bBhHoO] {
652 yylloc.first_line = start_line;
653 yylloc.first_column = start_column;
654 yylloc.last_line = current_line;
655 yylloc.last_column = current_column + 2;
656 Location loc(infile, yylloc);
657 int ret_val = TOK_errval;
658 switch (yytext[1]) {
659 case 'b': {
660 Location loc2(infile, current_line, current_column + 1, current_line,
661 current_column + 2);
662 loc2.warning("The last character of a bitstring literal should be "
663 "`B' instead of `b'");
664 /* no break */ }
665 case 'B':
666 if (valid_bit) {
667 if (contains_ws) loc.warning("Bitstring %s contains whitespace and/or "
668 "newline character(s)", contains_match ? "match" : "value");
669 ret_val = contains_match ? BitStringMatch : Bstring;
670 yylval.string_val = new string(binstr);
671 } else loc.error("Bitstring value contains invalid character");
672 break;
673 case 'h': {
674 Location loc2(infile, current_line, current_column + 1, current_line,
675 current_column + 2);
676 loc2.warning("The last character of a hexstring literal should be "
677 "`H' instead of `h'");
678 /* no break */ }
679 case 'H':
680 if (contains_ws) loc.warning("Hexstring %s contains whitespace and/or "
681 "newline character(s)", contains_match ? "match" : "value");
682 ret_val = contains_match ? HexStringMatch : Hstring;
683 yylval.string_val = new string(binstr);
684 break;
685 case 'o': {
686 Location loc2(infile, current_line, current_column + 1, current_line,
687 current_column + 2);
688 loc2.warning("The last character of an octetstring literal should be "
689 "`O' instead of `o'");
690 /* no break */ }
691 case 'O':
692 if (valid_oct && !half_oct) {
693 if (contains_ws) loc.warning("Octetstring %s contains whitespace "
694 "and/or newline character(s)", contains_match ? "match" : "value");
695 ret_val = contains_match ? OctetStringMatch : Ostring;
696 yylval.string_val = new string(binstr);
697 } else if (contains_match) {
698 loc.error("Octetstring match contains half octet(s)");
699 } else {
700 loc.error("Octetstring value contains odd number of hexadecimal "
701 "digits");
702 }
703 }
704 MD5_Update(&md5_ctx, binstr, strlen(binstr));
705 Free(binstr);
706 update_md5();
707 BEGIN(INITIAL);
708 current_column += 2;
709 if (dot_flag) {
710 backup_token = ret_val;
711 backup_lval = yylval;
712 backup_lloc = yylloc;
713 RETURN_SAVED_DOT;
714 } else return ret_val;
715 }
716
717 "'" {
718 yylloc.first_line = start_line;
719 yylloc.first_column = start_column;
720 current_column++;
721 yylloc.last_line = current_line;
722 yylloc.last_column = current_column;
723 Location loc(infile, yylloc);
724 loc.error("Invalid binary string literal. Expecting `B', `H' or `O' after "
725 "the closing `''");
726 MD5_Update(&md5_ctx, binstr, strlen(binstr));
727 Free(binstr);
728 BEGIN(INITIAL);
729 RETURN_NOLOCUPD(TOK_errval);
730 }
731
732 . {
733 Location loc(infile, current_line, current_column, current_line,
734 current_column + 1);
735 int c = (unsigned char)yytext[0];
736 loc.error("Invalid character `%c' (0x%02X) in binary string",
737 isprint(c) ? c : '?', c);
738 MD5_Update(&md5_ctx, binstr, strlen(binstr));
739 Free(binstr);
740 MD5_Update(&md5_ctx, yytext, 1);
741 current_column++;
742 BEGIN(SC_binstring_bad);
743 }
744
745} /* SC_binstring scope */
746
747<SC_binstring_bad> /* -------- SC_binstring_bad scope -------------- */
748{
749
750 {WHITESPACE}+ current_column += yyleng;
751
752 {WHITESPACE}*{NEWLINE} {
753 current_line++;
754 current_column = 0;
755 }
756
757 "'"[bBhHoO]? {
758 current_column += yyleng;
759 yylloc.first_line = start_line;
760 yylloc.first_column = start_column;
761 yylloc.last_line = current_line;
762 yylloc.last_column = current_column;
763 BEGIN(INITIAL);
764 RETURN_NOLOCUPD(TOK_errval);
765 }
766
767 . {
768 MD5_Update(&md5_ctx, yytext, yyleng);
769 current_column++;
770 }
771
772} /* SC_binstring_bad scope */
773
774<SC_cstring> /* -------- SC_cstring scope -------------- */
775{
776
777 \\?{NEWLINE} { /* newline possibly preceded by backslash */
778 yylval.str = mputstr(yylval.str, yytext);
779 current_line++;
780 current_column = 0;
781 }
782
783 \"\"|\\. { /* two doublequotes or any backslash-escaped char */
784 yylval.str = mputstr(yylval.str, yytext);
785 current_column += 2;
786 /* Note that both get added ("external representation").
787 * parse_charstring_value() in charstring_la.l is responsible
788 * for transforming the string to "internal representation" */
789 }
790
791 \" {
792 current_column++;
793 yylloc.first_line = start_line;
794 yylloc.first_column = start_column;
795 yylloc.last_line = current_line;
796 yylloc.last_column = current_column;
797 MD5_Update(&md5_ctx, yylval.str, strlen(yylval.str));
798 update_md5();
799 BEGIN(INITIAL);
800 if (dot_flag) {
801 backup_token = Cstring;
802 backup_lval = yylval;
803 backup_lloc = yylloc;
804 RETURN_SAVED_DOT;
805 } else return Cstring;
806 }
807
808 . {
809 yylval.str = mputc(yylval.str, yytext[0]);
810 current_column++;
811 }
812
813} /* SC_cstring scope */
814
815 /* Macros */
816
817"%moduleId" {
818 yylval.macrotype = Value::MACRO_MODULEID;
819 RETURN_LVAL(MacroValue);
820}
821"%fileName" {
822 yylval.macrotype = Value::MACRO_FILENAME;
823 RETURN_LVAL(MacroValue);
824}
825"%lineNumber" {
826 yylval.macrotype = Value::MACRO_LINENUMBER;
827 RETURN_LVAL(MacroValue);
828}
829"%definitionId" {
830 yylval.macrotype = Value::MACRO_DEFINITIONID;
831 RETURN_LVAL(MacroValue);
832}
833"%testcaseId" {
834 yylval.macrotype = Value::MACRO_TESTCASEID;
835 RETURN_LVAL(MacroValue);
836}
837"%"{IDENTIFIER} {
838 fill_location();
839 Location loc(infile, yylloc);
840 loc.error("Invalid macro notation: `%s'", yytext);
841 RETURN_NOLOCUPD(TOK_errval);
842}
843
844"__MODULE__" {
845 yylval.macrotype = Value::MACRO_MODULEID;
846 RETURN_LVAL(MacroValue);
847}
848"__FILE__" {
849 yylval.macrotype = Value::MACRO_FILEPATH;
850 RETURN_LVAL(MacroValue);
851}
852"__BFILE__" {
853 yylval.macrotype = Value::MACRO_BFILENAME;
854 RETURN_LVAL(MacroValue);
855}
856"__LINE__" {
857 yylval.macrotype = Value::MACRO_LINENUMBER_C;
858 RETURN_LVAL(MacroValue);
859}
860"__SCOPE__" {
861 yylval.macrotype = Value::MACRO_SCOPE;
862 RETURN_LVAL(MacroValue);
863}
864"__TESTCASE__" {
865 yylval.macrotype = Value::MACRO_TESTCASEID;
866 RETURN_LVAL(MacroValue);
867}
868"__"{IDENTIFIER}"__" {
869 fill_location();
870 Location loc(infile, yylloc);
871 loc.error("Invalid macro notation: `%s'", yytext);
872 RETURN_NOLOCUPD(TOK_errval);
873}
874
875 /* Multi-character operators */
876
877":=" RETURN(AssignmentChar);
878"\.\." RETURN(DotDot);
879"->" RETURN(PortRedirectSymbol);
880"==" RETURN(EQ);
881"!=" RETURN(NE);
882">=" RETURN(GE);
883"<=" RETURN(LE);
884"<<" RETURN(SL);
885">>" RETURN(SR);
886"<@" RETURN(RL);
887"@>" RETURN(_RR);
888
889"++" |
890"--" {
891 fill_location();
892 Location loc(infile, yylloc);
893 loc.error("Operator `%s' is reserved for future use", yytext);
894}
895
896 /* Invalid operators */
897
898"::=" {
899 fill_location();
900 Location loc(infile, yylloc);
901 loc.error("`::=' is not a valid assignment operator in TTCN-3. Did you mean "
902 "`:='?");
903 RETURN_NOLOCUPD(AssignmentChar);
904}
905
906"=" {
907 fill_location();
908 Location loc(infile, yylloc);
909 loc.error("A single `=' character cannot be used in TTCN-3. Did you mean "
910 "the assignment sign `:=' or the equality operator `=='?");
911 /* the former is more probable than the latter */
912 RETURN_NOLOCUPD(AssignmentChar);
913}
914
915"<>" {
916 fill_location();
917 Location loc(infile, yylloc);
918 loc.error("`<>' is not a valid comparison operator in TTCN-3. Did you mean "
919 "`!='?");
920 RETURN_NOLOCUPD(NE);
921}
922
923 /* Identifiers */
924
925{IDENTIFIER} {
926 yylval.id = new Identifier(Identifier::ID_TTCN, string(yyleng, yytext));
927 RETURN_LVAL(IDentifier);
928}
929
930 /* Single character tokens (brackets, operators, etc.) */
931
932\. {
933 update_md5();
934 if (dot_flag) {
935 /* store this dot in the backup */
936 backup_token = '.';
937 backup_lloc.first_line = current_line;
938 backup_lloc.first_column = current_column;
939 current_column++;
940 backup_lloc.last_line = current_line;
941 backup_lloc.last_column = current_column;
942 /* return the dot that was found previously */
943 RETURN_SAVED_DOT;
944 } else {
945 dot_flag = true;
946 dot_line = current_line;
947 dot_column = current_column;
948 current_column++;
949 }
950}
951
952[()\[\]{}+\-\*/&:;,<>\?!] RETURN(*yytext);
953
954 /* Invalid characters */
955
956. {
957 fill_location();
958 Location loc(infile, yylloc);
959 int c = (unsigned char)yytext[0];
960 loc.error("Character `%c' (0x%02X) is not used in TTCN-3",
961 isprint(c) ? c : '?', c);
962}
963
964 /* EOF rule */
965
966<*><<EOF>> {
967 if (YY_START != INITIAL) {
968 Location loc(infile, start_line, start_column, current_line,
969 current_column);
970 switch (YY_START) {
971 case SC_blockcomment:
972 loc.error("Unterminated block comment");
973 break;
974 case SC_binstring:
975 Free(binstr);
976 /* no break */
977 case SC_binstring_bad:
978 loc.error("Unterminated binary string literal");
979 break;
980 case SC_cstring:
981 Free(yylval.str);
982 loc.error("Unterminated character string literal");
983 }
984 BEGIN(INITIAL);
985 }
986 if (dot_flag) {
987 dot_flag = false;
988 RETURN_SAVED_DOT;
989 } else {
990 yylloc.first_line = current_line;
991 yylloc.first_column = current_column;
992 yylloc.last_line = current_line;
993 yylloc.last_column = current_column + 1;
994 return EOF;
995 }
996}
997
998%%
999
1000void init_ttcn3_lex()
1001{
1002 dot_flag = false;
1003 current_line = 1;
1004 current_column = 0;
1005 real_infile = infile;
1006 real_lineno_offset = 0;
1007 MD5_Init(&md5_ctx);
1008}
1009
1010void init_erroneous_lex(const char* p_infile, int p_line, int p_column)
1011{
1012 infile = p_infile;
1013 current_line = p_line;
1014 current_column = p_column;
1015 real_infile = infile;
1016 real_lineno_offset = 0;
1017 dot_flag = false;
1018}
1019
1020void free_dot_flag_stuff()
1021{
1022 if (dot_flag) {
1023 dot_flag = false;
1024 /* clean up the semantic value of the token that was backed up */
1025 switch (backup_token) {
1026 case IDentifier:
1027 delete backup_lval.id;
1028 break;
1029 case Bstring:
1030 case Hstring:
1031 case Ostring:
1032 case BitStringMatch:
1033 case HexStringMatch:
1034 case OctetStringMatch:
1035 delete backup_lval.string_val;
1036 break;
1037 case Cstring:
1038 Free(backup_lval.str);
1039 default:
1040 break;
1041 }
1042 }
1043}
1044
1045void free_ttcn3_lex()
1046{
1047 free_dot_flag_stuff();
1048 fclose(ttcn3_in);
1049 ttcn3_lex_destroy();
1050}
1051
1052/* called from ttcn3_parse_file to finalize MD5 and add it to the module */
1053void set_md5_checksum(Ttcn::Module *m)
1054{
1055 unsigned char md5_sum[MD5_DIGEST_LENGTH];
1056 MD5_Final(md5_sum, &md5_ctx);
1057 m->set_checksum(sizeof(md5_sum), md5_sum);
1058}
This page took 0.062953 seconds and 5 git commands to generate.