1 /******************************************************************************
2 * Copyright (c) 2000-2015 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 ******************************************************************************/
9 * ASN1:1997 lexical analyzer
10 * Written by Matyas Forstner
18 %option never-interactive
19 %option prefix="asn1_yy"
21 %{ /* ****************** C declarations ***************** */
24 #include "../string.hh"
25 #include "../Identifier.hh"
26 #include "../Setting.hh"
27 #include "../Value.hh"
28 #include "TokenBuf.hh"
30 using namespace Common;
34 * The name of the file which is under parsing.
36 const char *asn1_infile;
38 * When this flag is set, then the special internal TITAN-tokens are
41 bool asn1_yy_parse_internal=false;
45 void asn1la_newfile(const char *filename);
46 void asn1la_newtokenbuf(TokenBuf *tb);
49 static int commentlevel=0;
50 static int commentbeginlineno=0;
51 static TokenBuf *asn1_tokenbuf=0;
52 static TokenBuf *asn1_tokenbuf_curr=0;
54 static void id_replace_underscores(char *s);
55 static void bhstring_remove_whitespaces(char *s);
56 static void cstring_remove_newlines(char *s);
58 %} /* ***************** definitions ***************** */
60 /* start conditions */
61 %x SC_LINECOMMENT SC_COMMENT SC_COMMENT_END
65 WHITESPACE [ \t\x0A\x0B\x0C\x0D]+
66 NEWLINE [\x0A\x0B\x0C\x0D]
69 UPPERIDENTIFIER [A-Z]([\-_]?[A-Za-z0-9]+)*
71 LOWERIDENTIFIER [a-z]([\-_]?[A-Za-z0-9]+)*
74 ampUPPERIDENTIFIER \&{UPPERIDENTIFIER}
75 ampLOWERIDENTIFIER \&{LOWERIDENTIFIER}
78 NUMBER ([1-9][0-9]*)|0
80 REALNUMBER {NUMBER}(\.[0-9]+)?([eE][+\-]?{NUMBER})?
82 BSTRING '([01]|{WHITESPACE})*'B
85 HSTRING '([0-9A-F]|{WHITESPACE})*'H
87 HSTRING_BAD_OSTRING '([0-9A-F]|{WHITESPACE})*'O
90 CSTRING \"([^"]|(\"\"))*\"
93 SEPARATOR ({WHITESPACE}|{COMMENT})
95 PERPERCOMMENT "//"[^\x0A\x0B\x0C\x0D]*{NEWLINE}
97 TITAN "$#&&&(#TITAN$#&&^#% "
98 TITAN_ID [A-Za-z0-9 \-_]+
100 %% /* ***************** rules ************************* */
103 if(asn1_yy_parse_internal)
104 yy_push_state(SC_TITAN);
106 Location loc(asn1_infile, yylineno);
107 loc.error("Unexpected `%s'.", yytext);
111 <SC_TITAN> /* -------- SC_TITAN scope -------------- */
116 return KW_TITAN_Assignments;
119 "UpperIdentifier\""{TITAN_ID}"\"" {
121 yytext[strlen(yytext)-1]='\0';
122 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext+16));
123 return TOK_UpperIdentifier;
126 } /* ------------------- End of SC_TITAN scope -------- */
131 yy_push_state(SC_LINECOMMENT);
136 commentbeginlineno=yylineno;
137 yy_push_state(SC_COMMENT);
141 Location loc(asn1_infile, yylineno-1);
142 loc.error("This style of comment is not permitted in ASN.1");
146 "::=" {return TOK_Assignment;}
148 Location loc(asn1_infile, yylineno);
149 loc.error("`:=' is not valid in ASN.1. Did you mean `::='?");
150 return TOK_Assignment;
152 "..." {return TOK_Ellipsis;}
153 ".." {return TOK_RangeSeparator;}
154 "[[" {return TOK_LeftVersionBrackets;}
155 "]]" {return TOK_RightVersionBrackets;}
174 "ABSENT" {return KW_ABSENT;}
176 "ABSTRACT-SYNTAX" {return KW_ABSTRACT_SYNTAX;}
178 "ALL" {return KW_ALL;}
179 "ANY" {return KW_ANY;}
180 "APPLICATION" {return KW_APPLICATION;}
181 "AUTOMATIC" {return KW_AUTOMATIC;}
182 "BEGIN" {return KW_BEGIN;}
183 "BIT" {return KW_BIT;}
184 "BMPString" {return KW_BMPString;}
185 "BOOLEAN" {return KW_BOOLEAN;}
187 "CHARACTER" {return KW_CHARACTER;}
188 "CHOICE" {return KW_CHOICE;}
189 "CLASS" {return KW_CLASS;}
190 "COMPONENT" {return KW_COMPONENT;}
191 "COMPONENTS" {return KW_COMPONENTS;}
192 "CONSTRAINED" {return KW_CONSTRAINED;}
193 "CONTAINING" {return KW_CONTAINING;}
194 "DEFAULT" {return KW_DEFAULT;}
195 "DEFINED" {return KW_DEFINED;}
196 "DEFINITIONS" {return KW_DEFINITIONS;}
197 "EMBEDDED" {return KW_EMBEDDED;}
198 "ENCODED" {return KW_ENCODED;}
199 "END" {return KW_END;}
200 "ENUMERATED" {return KW_ENUMERATED;}
201 "EXCEPT" {return KW_EXCEPT;}
202 "EXPLICIT" {return KW_EXPLICIT;}
203 "EXPORTS" {return KW_EXPORTS;}
204 "EXTENSIBILITY" {return KW_EXTENSIBILITY;}
205 "EXTERNAL" {return KW_EXTERNAL;}
206 "FALSE" {return KW_FALSE;}
207 "FROM" {return KW_FROM;}
208 "GeneralizedTime" {return KW_GeneralizedTime;}
209 "GeneralString" {return KW_GeneralString;}
210 "GraphicString" {return KW_GraphicString;}
211 "IA5String" {return KW_IA5String;}
212 "IDENTIFIER" {return KW_IDENTIFIER;}
213 "IMPLICIT" {return KW_IMPLICIT;}
214 "IMPLIED" {return KW_IMPLIED;}
215 "IMPORTS" {return KW_IMPORTS;}
216 "INCLUDES" {return KW_INCLUDES;}
217 "INSTANCE" {return KW_INSTANCE;}
218 "INTEGER" {return KW_INTEGER;}
219 "INTERSECTION" {return KW_INTERSECTION;}
220 "ISO646String" {return KW_ISO646String;}
221 "MAX" {return KW_MAX;}
222 "MIN" {return KW_MIN;}
223 "MINUS-INFINITY" {return KW_MINUS_INFINITY;}
224 "NOT-A-NUMBER" {return KW_NOT_A_NUMBER;}
225 "NULL" {return KW_NULL;}
226 "NumericString" {return KW_NumericString;}
227 "OBJECT" {return KW_OBJECT;}
228 "ObjectDescriptor" {return KW_ObjectDescriptor;}
229 "OCTET" {return KW_OCTET;}
231 "OPTIONAL" {return KW_OPTIONAL;}
232 "PATTERN" {return KW_PATTERN;}
233 "PDV" {return KW_PDV;}
234 "PLUS-INFINITY" {return KW_PLUS_INFINITY;}
235 "PRESENT" {return KW_PRESENT;}
236 "PrintableString" {return KW_PrintableString;}
237 "PRIVATE" {return KW_PRIVATE;}
238 "REAL" {return KW_REAL;}
239 "RELATIVE-OID" {return KW_RELATIVE_OID;}
240 "SEQUENCE" {return KW_SEQUENCE;}
241 "SET" {return KW_SET;}
242 "SIZE" {return KW_SIZE;}
243 "STRING" {return KW_STRING;}
244 "SYNTAX" {return KW_SYNTAX;}
245 "T61String" {return KW_T61String;}
246 "TAGS" {return KW_TAGS;}
247 "TeletexString" {return KW_TeletexString;}
248 "TRUE" {return KW_TRUE;}
250 "TYPE-IDENTIFIER" {return KW_TYPE_IDENTIFIER;}
252 "UNION" {return KW_UNION;}
253 "UNIQUE" {return KW_UNIQUE;}
254 "UNIVERSAL" {return KW_UNIVERSAL;}
255 "UniversalString" {return KW_UniversalString;}
256 "UTCTime" {return KW_UTCTime;}
257 "UTF8String" {return KW_UTF8String;}
258 "VideotexString" {return KW_VideotexString;}
259 "VisibleString" {return KW_VisibleString;}
260 "WITH" {return KW_WITH;}
263 id_replace_underscores(yytext);
264 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
265 return TOK_LowerIdentifier;
269 id_replace_underscores(yytext);
270 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
271 return TOK_UpperIdentifier;
274 {ampUPPERIDENTIFIER} {
275 id_replace_underscores(yytext);
276 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
277 return TOK_ampUpperIdentifier;
280 {ampLOWERIDENTIFIER} {
281 id_replace_underscores(yytext);
282 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
283 return TOK_ampLowerIdentifier;
287 Location loc(asn1_infile, yylineno);
288 yylval.i = new int_val_t(yytext, loc);
293 Location loc(asn1_infile, yylineno);
294 yylval.value = new Value(Value::V_REAL, string2Real(yytext, loc));
295 return TOK_RealNumber;
299 bhstring_remove_whitespaces(yytext);
300 yytext[strlen(yytext)-2]='\0';
301 yylval.value=new Value(Value::V_BSTR, new string(yytext+1));
306 Location loc(asn1_infile, yylineno);
307 loc.error("Invalid bstring: %s.", yytext);
308 yylval.value=new Value(Value::V_BSTR, new string());
313 bhstring_remove_whitespaces(yytext);
314 yytext[strlen(yytext)-2]='\0';
315 yylval.value=new Value(Value::V_HSTR, new string(yytext+1));
320 Location loc(asn1_infile, yylineno);
321 loc.error("Invalid hstring: %s.", yytext);
322 yylval.value=new Value(Value::V_HSTR, new string());
326 {HSTRING_BAD_OSTRING} {
328 ostr[ostr.size()-1]='H';
329 Location loc(asn1_infile, yylineno);
330 loc.error("Invalid suffix `O' in %s. Did you mean the hstring %s?",
331 yytext, ostr.c_str());
332 bhstring_remove_whitespaces(yytext);
333 yytext[strlen(yytext)-2]='\0';
334 yylval.value=new Value(Value::V_HSTR, new string(yytext+1));
339 yytext[strlen(yytext)-1]='\0';
340 cstring_remove_newlines(yytext+1);
341 yylval.str=new string(yytext+1);
346 Location loc(asn1_infile, yylineno);
347 loc.error("Invalid cstring: %s. Perhaps you wanted to use quotation"
348 " marks (\") instead of apostrophes (')?", yytext);
349 yytext[strlen(yytext)-1]='\0';
350 yylval.str=new string(yytext+1);
358 Location loc(asn1_infile, yylineno);
359 loc.error("Unmatched `*/'");
363 Location loc(asn1_infile, yylineno);
364 loc.error("`%c' (0x%02X) character is not used in ASN.1",
365 (unsigned char)yytext[0]>31?(unsigned char)yytext[0]:'?',
366 (unsigned char)yytext[0]);
373 <SC_LINECOMMENT> /* -------- SC_LINECOMMENT scope -------------- */
387 } /* ------------------- End of SC_LINECOMMENT scope --------*/
389 <SC_COMMENT,SC_COMMENT_END><<EOF>> {
390 Location loc(asn1_infile, commentbeginlineno);
391 loc.error("Unmatched `/*'");
392 while(yy_top_state()!=INITIAL) yy_pop_state();
397 <SC_COMMENT> /* -------- SC_COMMENT scope -------------- */
404 "*" {yy_push_state(SC_COMMENT_END);}
408 } /* ------------------- End of SC_COMMENT scope --------*/
410 <SC_COMMENT_END> /* ----- SC_COMMENT_END scope -------------- */
418 if(!commentlevel) yy_pop_state();
421 [^*/] {yy_pop_state();}
423 } /* ------------------- End of SC_COMMENT_END scope --------*/
430 asn1_tokenbuf=new TokenBuf();
431 Asn::Assignments::create_spec_asss();
436 Asn::Assignments::destroy_spec_asss();
437 delete asn1_tokenbuf;
440 void asn1la_newfile(const char *filename)
442 asn1_tokenbuf->reset(filename);
443 asn1la_newtokenbuf(asn1_tokenbuf);
446 void asn1la_newtokenbuf(TokenBuf *tb)
449 FATAL_ERROR("asn1la_newtokenbuf(): tb is NULL");
450 asn1_tokenbuf_curr=tb;
451 asn1_infile=asn1_tokenbuf_curr->get_filename();
455 void id_replace_underscores(char *s)
461 if(!origid) origid=mputstr(origid, s);
467 Location loc(asn1_infile, yylineno);
468 loc.error("`%s' is not a valid ASN.1 identifier. Did you mean `%s'?",
474 void bhstring_remove_whitespaces(char *s) {
476 for(p1=p2=s; *p2; p2++) {
478 case ' ': // whitespace, no newline chars
480 case 0x0A: // newline chars
492 void cstring_remove_newlines(char *s) {
494 char *p_r, *p_w, *p_b;
495 enum {NO_WS, /**< no whitespace */
496 WS, /**< whitespace, but not newline */
500 p_r reads the string s;
501 p_w writes into the string s;
502 p_b is a bookmark for writing; shows the last non-whitespace character+1,
504 if state is NL, then the next whitespaces must be eaten up;
506 for(p_w=p_b=p_r=s; *p_r; p_w++, p_r++) {
508 case ' ': // whitespace, no newline chars
510 if(state==NO_WS) {p_b=p_w; state=WS;}
512 case 0x0A: // newline chars (LF,VT,FF,CR)
525 default: // not whitespace chars
526 if(state==NL) p_w=p_b;
530 if (*p_r=='"' && *(p_r+1)=='"') { // On the first of two QUOTATION MARKs.
531 p_w--; // Back up writing pos. The next " will overwrite this one.
539 return asn1_tokenbuf_curr->lex();