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
16 * Szabo, Janos Zoltan – initial implementation
18 ******************************************************************************/
20 * ASN1:1997 lexical analyzer
21 * Written by Matyas Forstner
29 %option never-interactive
30 %option prefix="asn1_yy"
32 %{ /* ****************** C declarations ***************** */
35 #include "../string.hh"
36 #include "../Identifier.hh"
37 #include "../Setting.hh"
38 #include "../Value.hh"
39 #include "TokenBuf.hh"
41 using namespace Common;
45 * The name of the file which is under parsing.
47 const char *asn1_infile;
49 * When this flag is set, then the special internal TITAN-tokens are
52 bool asn1_yy_parse_internal=false;
56 void asn1la_newfile(const char *filename);
57 void asn1la_newtokenbuf(TokenBuf *tb);
60 static int commentlevel=0;
61 static int commentbeginlineno=0;
62 static TokenBuf *asn1_tokenbuf=0;
63 static TokenBuf *asn1_tokenbuf_curr=0;
65 static void id_replace_underscores(char *s);
66 static void bhstring_remove_whitespaces(char *s);
67 static void cstring_remove_newlines(char *s);
69 %} /* ***************** definitions ***************** */
71 /* start conditions */
72 %x SC_LINECOMMENT SC_COMMENT SC_COMMENT_END
76 WHITESPACE [ \t\x0A\x0B\x0C\x0D]+
77 NEWLINE [\x0A\x0B\x0C\x0D]
80 UPPERIDENTIFIER [A-Z]([\-_]?[A-Za-z0-9]+)*
82 LOWERIDENTIFIER [a-z]([\-_]?[A-Za-z0-9]+)*
85 ampUPPERIDENTIFIER \&{UPPERIDENTIFIER}
86 ampLOWERIDENTIFIER \&{LOWERIDENTIFIER}
89 NUMBER ([1-9][0-9]*)|0
91 REALNUMBER {NUMBER}(\.[0-9]+)?([eE][+\-]?{NUMBER})?
93 BSTRING '([01]|{WHITESPACE})*'B
96 HSTRING '([0-9A-F]|{WHITESPACE})*'H
98 HSTRING_BAD_OSTRING '([0-9A-F]|{WHITESPACE})*'O
101 CSTRING \"([^"]|(\"\"))*\"
104 SEPARATOR ({WHITESPACE}|{COMMENT})
106 PERPERCOMMENT "//"[^\x0A\x0B\x0C\x0D]*{NEWLINE}
108 TITAN "$#&&&(#TITAN$#&&^#% "
109 TITAN_ID [A-Za-z0-9 \-_]+
111 %% /* ***************** rules ************************* */
114 if(asn1_yy_parse_internal)
115 yy_push_state(SC_TITAN);
117 Location loc(asn1_infile, yylineno);
118 loc.error("Unexpected `%s'.", yytext);
122 <SC_TITAN> /* -------- SC_TITAN scope -------------- */
127 return KW_TITAN_Assignments;
130 "UpperIdentifier\""{TITAN_ID}"\"" {
132 yytext[strlen(yytext)-1]='\0';
133 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext+16));
134 return TOK_UpperIdentifier;
137 } /* ------------------- End of SC_TITAN scope -------- */
142 yy_push_state(SC_LINECOMMENT);
147 commentbeginlineno=yylineno;
148 yy_push_state(SC_COMMENT);
152 Location loc(asn1_infile, yylineno-1);
153 loc.error("This style of comment is not permitted in ASN.1");
157 "::=" {return TOK_Assignment;}
159 Location loc(asn1_infile, yylineno);
160 loc.error("`:=' is not valid in ASN.1. Did you mean `::='?");
161 return TOK_Assignment;
163 "..." {return TOK_Ellipsis;}
164 ".." {return TOK_RangeSeparator;}
165 "[[" {return TOK_LeftVersionBrackets;}
166 "]]" {return TOK_RightVersionBrackets;}
185 "ABSENT" {return KW_ABSENT;}
187 "ABSTRACT-SYNTAX" {return KW_ABSTRACT_SYNTAX;}
189 "ALL" {return KW_ALL;}
190 "ANY" {return KW_ANY;}
191 "APPLICATION" {return KW_APPLICATION;}
192 "AUTOMATIC" {return KW_AUTOMATIC;}
193 "BEGIN" {return KW_BEGIN;}
194 "BIT" {return KW_BIT;}
195 "BMPString" {return KW_BMPString;}
196 "BOOLEAN" {return KW_BOOLEAN;}
198 "CHARACTER" {return KW_CHARACTER;}
199 "CHOICE" {return KW_CHOICE;}
200 "CLASS" {return KW_CLASS;}
201 "COMPONENT" {return KW_COMPONENT;}
202 "COMPONENTS" {return KW_COMPONENTS;}
203 "CONSTRAINED" {return KW_CONSTRAINED;}
204 "CONTAINING" {return KW_CONTAINING;}
205 "DEFAULT" {return KW_DEFAULT;}
206 "DEFINED" {return KW_DEFINED;}
207 "DEFINITIONS" {return KW_DEFINITIONS;}
208 "EMBEDDED" {return KW_EMBEDDED;}
209 "ENCODED" {return KW_ENCODED;}
210 "END" {return KW_END;}
211 "ENUMERATED" {return KW_ENUMERATED;}
212 "EXCEPT" {return KW_EXCEPT;}
213 "EXPLICIT" {return KW_EXPLICIT;}
214 "EXPORTS" {return KW_EXPORTS;}
215 "EXTENSIBILITY" {return KW_EXTENSIBILITY;}
216 "EXTERNAL" {return KW_EXTERNAL;}
217 "FALSE" {return KW_FALSE;}
218 "FROM" {return KW_FROM;}
219 "GeneralizedTime" {return KW_GeneralizedTime;}
220 "GeneralString" {return KW_GeneralString;}
221 "GraphicString" {return KW_GraphicString;}
222 "IA5String" {return KW_IA5String;}
223 "IDENTIFIER" {return KW_IDENTIFIER;}
224 "IMPLICIT" {return KW_IMPLICIT;}
225 "IMPLIED" {return KW_IMPLIED;}
226 "IMPORTS" {return KW_IMPORTS;}
227 "INCLUDES" {return KW_INCLUDES;}
228 "INSTANCE" {return KW_INSTANCE;}
229 "INTEGER" {return KW_INTEGER;}
230 "INTERSECTION" {return KW_INTERSECTION;}
231 "ISO646String" {return KW_ISO646String;}
232 "MAX" {return KW_MAX;}
233 "MIN" {return KW_MIN;}
234 "MINUS-INFINITY" {return KW_MINUS_INFINITY;}
235 "NOT-A-NUMBER" {return KW_NOT_A_NUMBER;}
236 "NULL" {return KW_NULL;}
237 "NumericString" {return KW_NumericString;}
238 "OBJECT" {return KW_OBJECT;}
239 "ObjectDescriptor" {return KW_ObjectDescriptor;}
240 "OCTET" {return KW_OCTET;}
242 "OPTIONAL" {return KW_OPTIONAL;}
243 "PATTERN" {return KW_PATTERN;}
244 "PDV" {return KW_PDV;}
245 "PLUS-INFINITY" {return KW_PLUS_INFINITY;}
246 "PRESENT" {return KW_PRESENT;}
247 "PrintableString" {return KW_PrintableString;}
248 "PRIVATE" {return KW_PRIVATE;}
249 "REAL" {return KW_REAL;}
250 "RELATIVE-OID" {return KW_RELATIVE_OID;}
251 "SEQUENCE" {return KW_SEQUENCE;}
252 "SET" {return KW_SET;}
253 "SIZE" {return KW_SIZE;}
254 "STRING" {return KW_STRING;}
255 "SYNTAX" {return KW_SYNTAX;}
256 "T61String" {return KW_T61String;}
257 "TAGS" {return KW_TAGS;}
258 "TeletexString" {return KW_TeletexString;}
259 "TRUE" {return KW_TRUE;}
261 "TYPE-IDENTIFIER" {return KW_TYPE_IDENTIFIER;}
263 "UNION" {return KW_UNION;}
264 "UNIQUE" {return KW_UNIQUE;}
265 "UNIVERSAL" {return KW_UNIVERSAL;}
266 "UniversalString" {return KW_UniversalString;}
267 "UTCTime" {return KW_UTCTime;}
268 "UTF8String" {return KW_UTF8String;}
269 "VideotexString" {return KW_VideotexString;}
270 "VisibleString" {return KW_VisibleString;}
271 "WITH" {return KW_WITH;}
274 id_replace_underscores(yytext);
275 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
276 return TOK_LowerIdentifier;
280 id_replace_underscores(yytext);
281 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
282 return TOK_UpperIdentifier;
285 {ampUPPERIDENTIFIER} {
286 id_replace_underscores(yytext);
287 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
288 return TOK_ampUpperIdentifier;
291 {ampLOWERIDENTIFIER} {
292 id_replace_underscores(yytext);
293 yylval.id=new Identifier(Identifier::ID_ASN, string(yytext));
294 return TOK_ampLowerIdentifier;
298 Location loc(asn1_infile, yylineno);
299 yylval.i = new int_val_t(yytext, loc);
304 Location loc(asn1_infile, yylineno);
305 yylval.value = new Value(Value::V_REAL, string2Real(yytext, loc));
306 return TOK_RealNumber;
310 bhstring_remove_whitespaces(yytext);
311 yytext[strlen(yytext)-2]='\0';
312 yylval.value=new Value(Value::V_BSTR, new string(yytext+1));
317 Location loc(asn1_infile, yylineno);
318 loc.error("Invalid bstring: %s.", yytext);
319 yylval.value=new Value(Value::V_BSTR, new string());
324 bhstring_remove_whitespaces(yytext);
325 yytext[strlen(yytext)-2]='\0';
326 yylval.value=new Value(Value::V_HSTR, new string(yytext+1));
331 Location loc(asn1_infile, yylineno);
332 loc.error("Invalid hstring: %s.", yytext);
333 yylval.value=new Value(Value::V_HSTR, new string());
337 {HSTRING_BAD_OSTRING} {
339 ostr[ostr.size()-1]='H';
340 Location loc(asn1_infile, yylineno);
341 loc.error("Invalid suffix `O' in %s. Did you mean the hstring %s?",
342 yytext, ostr.c_str());
343 bhstring_remove_whitespaces(yytext);
344 yytext[strlen(yytext)-2]='\0';
345 yylval.value=new Value(Value::V_HSTR, new string(yytext+1));
350 yytext[strlen(yytext)-1]='\0';
351 cstring_remove_newlines(yytext+1);
352 yylval.str=new string(yytext+1);
357 Location loc(asn1_infile, yylineno);
358 loc.error("Invalid cstring: %s. Perhaps you wanted to use quotation"
359 " marks (\") instead of apostrophes (')?", yytext);
360 yytext[strlen(yytext)-1]='\0';
361 yylval.str=new string(yytext+1);
369 Location loc(asn1_infile, yylineno);
370 loc.error("Unmatched `*/'");
374 Location loc(asn1_infile, yylineno);
375 loc.error("`%c' (0x%02X) character is not used in ASN.1",
376 (unsigned char)yytext[0]>31?(unsigned char)yytext[0]:'?',
377 (unsigned char)yytext[0]);
384 <SC_LINECOMMENT> /* -------- SC_LINECOMMENT scope -------------- */
398 } /* ------------------- End of SC_LINECOMMENT scope --------*/
400 <SC_COMMENT,SC_COMMENT_END><<EOF>> {
401 Location loc(asn1_infile, commentbeginlineno);
402 loc.error("Unmatched `/*'");
403 while(yy_top_state()!=INITIAL) yy_pop_state();
408 <SC_COMMENT> /* -------- SC_COMMENT scope -------------- */
415 "*" {yy_push_state(SC_COMMENT_END);}
419 } /* ------------------- End of SC_COMMENT scope --------*/
421 <SC_COMMENT_END> /* ----- SC_COMMENT_END scope -------------- */
429 if(!commentlevel) yy_pop_state();
432 [^*/] {yy_pop_state();}
434 } /* ------------------- End of SC_COMMENT_END scope --------*/
441 asn1_tokenbuf=new TokenBuf();
442 Asn::Assignments::create_spec_asss();
447 Asn::Assignments::destroy_spec_asss();
448 delete asn1_tokenbuf;
451 void asn1la_newfile(const char *filename)
453 asn1_tokenbuf->reset(filename);
454 asn1la_newtokenbuf(asn1_tokenbuf);
457 void asn1la_newtokenbuf(TokenBuf *tb)
460 FATAL_ERROR("asn1la_newtokenbuf(): tb is NULL");
461 asn1_tokenbuf_curr=tb;
462 asn1_infile=asn1_tokenbuf_curr->get_filename();
466 void id_replace_underscores(char *s)
472 if(!origid) origid=mputstr(origid, s);
478 Location loc(asn1_infile, yylineno);
479 loc.error("`%s' is not a valid ASN.1 identifier. Did you mean `%s'?",
485 void bhstring_remove_whitespaces(char *s) {
487 for(p1=p2=s; *p2; p2++) {
489 case ' ': // whitespace, no newline chars
491 case 0x0A: // newline chars
503 void cstring_remove_newlines(char *s) {
505 char *p_r, *p_w, *p_b;
506 enum {NO_WS, /**< no whitespace */
507 WS, /**< whitespace, but not newline */
511 p_r reads the string s;
512 p_w writes into the string s;
513 p_b is a bookmark for writing; shows the last non-whitespace character+1,
515 if state is NL, then the next whitespaces must be eaten up;
517 for(p_w=p_b=p_r=s; *p_r; p_w++, p_r++) {
519 case ' ': // whitespace, no newline chars
521 if(state==NO_WS) {p_b=p_w; state=WS;}
523 case 0x0A: // newline chars (LF,VT,FF,CR)
536 default: // not whitespace chars
537 if(state==NL) p_w=p_b;
541 if (*p_r=='"' && *(p_r+1)=='"') { // On the first of two QUOTATION MARKs.
542 p_w--; // Back up writing pos. The next " will overwrite this one.
550 return asn1_tokenbuf_curr->lex();