2 %option never-interactive
6 * Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
8 * This source code is free software; you can redistribute it
9 * and/or modify it in source code form under the terms of the GNU
10 * General Public License as published by the Free Software
11 * Foundation; either version 2 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
24 #ident "$Id: lexor.lex,v 1.96 2007/06/14 03:50:00 steve Exp $"
29 //# define YYSTYPE lexval
32 # include "compiler.h"
33 # include "parse_misc.h"
34 # include "parse_api.h"
38 # include "lexor_keyword.h"
41 # define YY_USER_INIT reset_lexor();
42 # define yylval VLlval
45 * Lexical location information is passed in the yylloc variable to th
46 * parser. The file names, strings, are kept in a list so that I can
47 * re-use them. The set_file_name function will return a pointer to
48 * the name as it exists in the list (and delete the passed string.)
49 * If the name is new, it will be added to the list.
51 extern YYLTYPE yylloc;
53 struct file_name_cell {
55 struct file_name_cell*next;
59 static struct file_name_cell*file_names = 0;
61 static const char* set_file_name(char*text)
63 struct file_name_cell*cur = file_names;
65 if (strcmp(cur->text, text) == 0) {
73 cur = new struct file_name_cell;
75 cur->next = file_names;
77 /* Check this file name with the list of library file
78 names. If there is a match, then turn on the
79 pform_library_flag. This is how the parser knows that
80 modules declared in this file are library modules. */
81 cur->library_flag = library_file_map[cur->text];
82 pform_library_flag = cur->library_flag;
87 extern void pform_set_timescale(int, int, const char*file, unsigned line);
90 static void line_directive();
91 static void line_directive2();
93 static verinum*make_unsized_binary(const char*txt);
94 static verinum*make_unsized_dec(const char*txt);
95 static verinum*make_unsized_octal(const char*txt);
96 static verinum*make_unsized_hex(const char*txt);
98 static int dec_buf_div2(char *buf);
100 static void process_timescale(const char*txt);
102 static int comment_enter;
118 ^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
119 ^"`line"[ ]+[0-9]+[ ]+\"[^\"]*\".* { line_directive2(); }
122 \n { yylloc.first_line += 1; }
124 /* C++ style comments start with / / and run to the end of the
125 current line. These are very easy to handle. */
127 "//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
128 <LCOMMENT>. { yymore(); }
129 <LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
132 /* The contents of C-style comments are ignored, like white space. */
134 "/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
135 <CCOMMENT>. { yymore(); }
136 <CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
137 <CCOMMENT>"*/" { BEGIN(comment_enter); }
140 "(*" { return K_PSTAR; }
141 "*)" { return K_STARP; }
142 "<<" { return K_LS; }
143 "<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
144 ">>" { return K_RS; }
145 ">>>" { return K_RSS; }
146 "**" { return K_POW; }
147 "<=" { return K_LE; }
148 ">=" { return K_GE; }
149 "=>" { return K_EG; }
150 "*>" { return K_SG; }
151 "==" { return K_EQ; }
152 "!=" { return K_NE; }
153 "===" { return K_CEQ; }
154 "!==" { return K_CNE; }
155 "||" { return K_LOR; }
156 "&&" { return K_LAND; }
157 "&&&" { return K_TAND; }
158 "~|" { return K_NOR; }
159 "~^" { return K_NXOR; }
160 "^~" { return K_NXOR; }
161 "~&" { return K_NAND; }
162 "->" { return K_TRIGGER; }
163 "+:" { return K_PO_POS; }
164 "-:" { return K_PO_NEG; }
166 /* Watch out for the tricky case of (*). Cannot parse this as "(*"
167 and ")", but since I know that this is really ( * ), replace it
168 with "*" and return that. */
169 "("{W}*"*"{W}*")" { return '*'; }
171 <EDGES>"]" { BEGIN(0); return yytext[0]; }
172 [}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
174 \" { BEGIN(CSTRING); }
175 <CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
176 <CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
177 <CSTRING>\n { BEGIN(0);
178 yylval.text = strdup(yytext);
179 VLerror(yylloc, "Missing close quote of string.");
180 yylloc.first_line += 1;
182 <CSTRING>\" { BEGIN(0);
183 yylval.text = strdup(yytext);
184 yylval.text[strlen(yytext)-1] = 0;
186 <CSTRING>. { yymore(); }
188 <UDPTABLE>\(\?0\) { return '_'; }
189 <UDPTABLE>\(\?1\) { return '+'; }
190 <UDPTABLE>\(\?[xX]\) { return '%'; }
191 <UDPTABLE>\(\?\?\) { return '*'; }
192 <UDPTABLE>\(01\) { return 'r'; }
193 <UDPTABLE>\(0[xX]\) { return 'Q'; }
194 <UDPTABLE>\(b[xX]\) { return 'q'; }
195 <UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
196 <UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
197 <UDPTABLE>\(0\?\) { return 'P'; }
198 <UDPTABLE>\(10\) { return 'f'; }
199 <UDPTABLE>\(1[xX]\) { return 'M'; }
200 <UDPTABLE>\(1\?\) { return 'N'; }
201 <UDPTABLE>\([xX]0\) { return 'F'; }
202 <UDPTABLE>\([xX]1\) { return 'R'; }
203 <UDPTABLE>\([xX]\?\) { return 'B'; }
204 <UDPTABLE>[bB] { return 'b'; }
205 <UDPTABLE>[lL] { return 'l'; /* IVL extension */ }
206 <UDPTABLE>[hH] { return 'h'; /* IVL extension */ }
207 <UDPTABLE>[fF] { return 'f'; }
208 <UDPTABLE>[rR] { return 'r'; }
209 <UDPTABLE>[xX] { return 'x'; }
210 <UDPTABLE>[nN] { return 'n'; }
211 <UDPTABLE>[pP] { return 'p'; }
212 <UDPTABLE>[01\?\*\-] { return yytext[0]; }
214 <EDGES>"01" { return K_edge_descriptor; }
215 <EDGES>"0x" { return K_edge_descriptor; }
216 <EDGES>"0z" { return K_edge_descriptor; }
217 <EDGES>"10" { return K_edge_descriptor; }
218 <EDGES>"1x" { return K_edge_descriptor; }
219 <EDGES>"1z" { return K_edge_descriptor; }
220 <EDGES>"x0" { return K_edge_descriptor; }
221 <EDGES>"x1" { return K_edge_descriptor; }
222 <EDGES>"z0" { return K_edge_descriptor; }
223 <EDGES>"z1" { return K_edge_descriptor; }
225 [a-zA-Z_][a-zA-Z0-9$_]* {
226 int rc = lexor_keyword_code(yytext, yyleng);
229 yylval.text = strdup(yytext);
230 if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
231 rc = PATHPULSE_IDENTIFIER;
237 if (! gn_cadence_types_enabled()) {
238 yylval.text = strdup(yytext);
259 yylval.text = strdup(yytext+1);
263 if (strcmp(yytext,"$setuphold") == 0)
265 if (strcmp(yytext,"$attribute") == 0)
267 if (strcmp(yytext,"$hold") == 0)
269 if (strcmp(yytext,"$period") == 0)
271 if (strcmp(yytext,"$recovery") == 0)
273 if (strcmp(yytext,"$recrem") == 0)
275 if (strcmp(yytext,"$setup") == 0)
277 if (strcmp(yytext,"$width") == 0)
279 yylval.text = strdup(yytext);
280 return SYSTEM_IDENTIFIER; }
283 \'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
284 return BASED_NUMBER; }
285 \'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
286 return BASED_NUMBER; }
287 \'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
288 return BASED_NUMBER; }
289 \'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
290 return BASED_NUMBER; }
293 yylval.number = make_unsized_dec(yytext);
296 [0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
297 yylval.realtime = new verireal(yytext);
300 [0-9][0-9_]*[Ee][+-]?[0-9][0-9_]* {
301 yylval.realtime = new verireal(yytext);
305 /* Notice and handle the timescale directive. */
307 ^{W}?`timescale { BEGIN(PPTIMESCALE); }
308 <PPTIMESCALE>.* { process_timescale(yytext); }
310 yylloc.first_line += 1;
314 /* These are directives that I do not yet support. I think that IVL
315 should handle these, not an external preprocessor. */
317 ^{W}?`celldefine{W}?.* { }
318 ^{W}?`delay_mode_distributed{W}?.* { }
319 ^{W}?`delay_mode_unit{W}?.* { }
320 ^{W}?`delay_mode_path{W}?.* { }
321 ^{W}?`disable_portfaults{W}?.* { }
322 ^{W}?`enable_portfaults{W}?.* { }
323 ^{W}?`endcelldefine{W}?.* { }
325 ^{W}?`nosuppress_faults{W}?.* { }
326 ^{W}?`nounconnected_drive{W}?.* { }
328 ^{W}?`resetall{W}?.* { }
329 ^{W}?`suppress_faults{W}?.* { }
330 ^{W}?`unconnected_drive{W}?.* { }
331 ^{W}?`uselib{W}?.* { }
333 /* Notice and handle the default_nettype directive. The lexor
334 detects the default_nettype keyword, and the second part of the
335 rule collects the rest of the line and processes it. We only need
336 to look for the first work, and interpret it. */
338 `default_nettype{W}? { BEGIN(PPDEFAULT_NETTYPE); }
339 <PPDEFAULT_NETTYPE>.* {
340 NetNet::Type net_type;
341 size_t wordlen = strcspn(yytext, " \t\f\r\n");
343 if (strcmp(yytext,"wire") == 0) {
344 net_type = NetNet::WIRE;
346 } else if (strcmp(yytext,"none") == 0) {
347 net_type = NetNet::NONE;
350 cerr << yylloc.text << ":" << yylloc.first_line
351 << " error: Net type " << yytext
352 << " is not a valid (and supported)"
353 << " default net type." << endl;
354 net_type = NetNet::WIRE;
357 pform_set_default_nettype(net_type, yylloc.text, yylloc.first_line);
359 <PPDEFAULT_NETTYPE>\n {
360 yylloc.first_line += 1;
364 /* These are directives that are not supported by me and should have
365 been handled by an external preprocessor such as ivlpp. */
368 cerr << yylloc.text << ":" << yylloc.first_line <<
369 ": `define not supported. Use an external preprocessor."
374 cerr << yylloc.text << ":" << yylloc.first_line <<
375 ": `else not supported. Use an external preprocessor."
380 cerr << yylloc.text << ":" << yylloc.first_line <<
381 ": `endif not supported. Use an external preprocessor."
386 cerr << yylloc.text << ":" << yylloc.first_line <<
387 ": `ifdef not supported. Use an external preprocessor."
392 cerr << yylloc.text << ":" << yylloc.first_line <<
393 ": `include not supported. Use an external preprocessor."
398 cerr << yylloc.text << ":" << yylloc.first_line <<
399 ": `undef not supported. Use an external preprocessor."
404 `{W} { cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
405 << "Stray tic (`) here. Perhaps you put white space" << endl;
406 cerr << yylloc.text << ":" << yylloc.first_line << ": : "
407 << "between the tic and preprocessor directive?"
411 /* Final catchall. something got lost or mishandled. */
413 . { cerr << yylloc.text << ":" << yylloc.first_line
414 << ": error: unmatched character (";
415 if (isgraph(yytext[0]))
418 cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
426 * The UDP state table needs some slightly different treatment by the
427 * lexor. The level characters are normally accepted as other things,
428 * so the parser needs to switch my mode when it believes in needs to.
430 void lex_start_table()
440 static verinum*make_unsized_binary(const char*txt)
442 bool sign_flag = false;
443 const char*ptr = txt;
444 assert(*ptr == '\'');
447 if (tolower(*ptr) == 's') {
452 assert(tolower(*ptr) == 'b');
455 while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
459 for (const char*idx = ptr ; *idx ; idx += 1)
460 if (*idx != '_') size += 1;
462 verinum::V*bits = new verinum::V[size];
468 bits[--idx] = verinum::V0;
471 bits[--idx] = verinum::V1;
473 case 'z': case 'Z': case '?':
474 bits[--idx] = verinum::Vz;
477 bits[--idx] = verinum::Vx;
482 fprintf(stderr, "%c\n", ptr[0]);
488 verinum*out = new verinum(bits, size, false);
489 out->has_sign(sign_flag);
495 static verinum*make_unsized_octal(const char*txt)
497 bool sign_flag = false;
498 const char*ptr = txt;
499 assert(*ptr == '\'');
502 if (tolower(*ptr) == 's') {
507 assert(tolower(*ptr) == 'o');
510 while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
514 for (const char*idx = ptr ; *idx ; idx += 1)
515 if (*idx != '_') size += 3;
517 verinum::V*bits = new verinum::V[size];
523 case '0': case '1': case '2': case '3':
524 case '4': case '5': case '6': case '7':
526 bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
527 bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
528 bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
531 bits[--idx] = verinum::Vx;
532 bits[--idx] = verinum::Vx;
533 bits[--idx] = verinum::Vx;
535 case 'z': case 'Z': case '?':
536 bits[--idx] = verinum::Vz;
537 bits[--idx] = verinum::Vz;
538 bits[--idx] = verinum::Vz;
548 verinum*out = new verinum(bits, size, false);
549 out->has_sign(sign_flag);
555 static verinum*make_unsized_hex(const char*txt)
557 bool sign_flag = false;
558 const char*ptr = txt;
559 assert(*ptr == '\'');
562 if (tolower(*ptr) == 's') {
566 assert(tolower(*ptr) == 'h');
569 while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
573 for (const char*idx = ptr ; *idx ; idx += 1)
574 if (*idx != '_') size += 4;
576 verinum::V*bits = new verinum::V[size];
582 case '0': case '1': case '2': case '3': case '4':
583 case '5': case '6': case '7': case '8': case '9':
585 bits[--idx] = (val&8) ? verinum::V1 : verinum::V0;
586 bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
587 bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
588 bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
590 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
591 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
592 val = tolower(*ptr) - 'a' + 10;
593 bits[--idx] = (val&8) ? verinum::V1 : verinum::V0;
594 bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
595 bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
596 bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
599 bits[--idx] = verinum::Vx;
600 bits[--idx] = verinum::Vx;
601 bits[--idx] = verinum::Vx;
602 bits[--idx] = verinum::Vx;
604 case 'z': case 'Z': case '?':
605 bits[--idx] = verinum::Vz;
606 bits[--idx] = verinum::Vz;
607 bits[--idx] = verinum::Vz;
608 bits[--idx] = verinum::Vz;
618 verinum*out = new verinum(bits, size, false);
619 out->has_sign(sign_flag);
625 /* Divide the integer given by the string by 2. Return the remainder bit. */
626 static int dec_buf_div2(char *buf)
629 int len = strlen(buf);
636 /* dst_ptr overwrites buf, but all characters that are overwritten
637 were already used by the reader. */
640 while(buf[pos] == '0')
643 for(; pos<len; ++pos){
647 assert(isdigit(buf[pos]));
649 partial= partial*10 + (buf[pos]-'0');
652 *dst_ptr = partial/2 + '0';
653 partial = partial & 1;
663 // If result of division was zero string, it should remain that way.
664 // Don't eat the last zero...
675 * Making a decimal number is much easier then the other base numbers
676 * because there are no z or x values to worry about. It is much
677 * harder then other base numbers because the width needed in bits is
681 static verinum*make_unsized_dec(const char*ptr)
684 bool signed_flag = false;
687 if (ptr[0] == '\'') {
688 /* The number has decorations of the form 'sd<digits>,
689 possibly with space between the d and the <digits>.
690 Also, the 's' is optional, and markes the number as
694 if (tolower(*ptr) == 's') {
699 assert(tolower(*ptr) == 'd');
702 while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
706 /* ... or an undecorated decimal number is passed
707 it. These numbers are treated as signed decimal. */
708 assert(isdigit(*ptr));
713 /* Copy the digits into a buffer that I can use to do in-place
716 while ((idx < sizeof buf) && (*ptr != 0)) {
725 if (idx == sizeof buf) {
726 fprintf(stderr, "Ridiculously long"
727 " decimal constant will be truncated!\n");
732 unsigned tmp_size = idx * 4 + 1;
733 verinum::V *bits = new verinum::V[tmp_size];
736 while (idx < tmp_size) {
737 int rem = dec_buf_div2(buf);
738 bits[idx++] = (rem == 1) ? verinum::V1 : verinum::V0;
741 assert(strcmp(buf, "0") == 0);
743 /* Now calculate the minimum number of bits needed to
744 represent this unsigned number. */
745 unsigned size = tmp_size;
746 while ((size > 1) && (bits[size-1] == verinum::V0))
749 /* Now account for the signedness. Don't leave a 1 in the high
750 bit if this is a signed number. */
751 if (signed_flag && (bits[size-1] == verinum::V1)) {
753 assert(size <= tmp_size);
756 verinum*res = new verinum(bits, size, false);
757 res->has_sign(signed_flag);
765 * The timescale parameter has the form:
766 * " <num> xs / <num> xs"
768 static void process_timescale(const char*txt)
771 const char*cp = txt + strspn(txt, " \t");
778 num = strtoul(cp, &tmp, 10);
780 VLerror(yylloc, "Invalid timescale string.");
789 VLerror(yylloc, "Invalid timescale unit number.");
794 cp += strspn(cp, " \t");
795 ctmp = cp + strcspn(cp, " \t/");
797 if (strncmp("s", cp, ctmp-cp) == 0) {
800 } else if (strncmp("ms", cp, ctmp-cp) == 0) {
803 } else if (strncmp("us", cp, ctmp-cp) == 0) {
806 } else if (strncmp("ns", cp, ctmp-cp) == 0) {
809 } else if (strncmp("ps", cp, ctmp-cp) == 0) {
812 } else if (strncmp("fs", cp, ctmp-cp) == 0) {
816 VLerror(yylloc, "Invalid timescale unit of measurement");
821 cp += strspn(cp, " \t/");
823 num = strtoul(cp, &tmp, 10);
825 VLerror(yylloc, "Invalid timescale string.");
834 VLerror(yylloc, "Invalid timescale precision number.");
839 cp += strspn(cp, " \t");
840 ctmp = cp + strcspn(cp, " \t\r");
842 if (strncmp("s", cp, ctmp-cp) == 0) {
845 } else if (strncmp("ms", cp, ctmp-cp) == 0) {
848 } else if (strncmp("us", cp, ctmp-cp) == 0) {
851 } else if (strncmp("ns", cp, ctmp-cp) == 0) {
854 } else if (strncmp("ps", cp, ctmp-cp) == 0) {
857 } else if (strncmp("fs", cp, ctmp-cp) == 0) {
861 VLerror(yylloc, "Invalid timescale precision units of measurement");
865 pform_set_timescale(unit, prec, yylloc.text, yylloc.first_line);
874 * The line directive matches lines of the form #line "foo" N and
875 * calls this function. Here I parse out the file name and line
876 * number, and change the yylloc to suite.
878 static void line_directive()
880 char*qt1 = strchr(yytext, '"');
884 char*qt2 = strchr(qt1, '"');
887 char*buf = new char[qt2-qt1+1];
888 strncpy(buf, qt1, qt2-qt1);
891 yylloc.text = set_file_name(buf);
894 yylloc.first_line = strtoul(qt2,0,0);
897 static void line_directive2()
899 assert(strncmp(yytext,"`line",5) == 0);
900 char*cp = yytext + strlen("`line");
901 cp += strspn(cp, " ");
902 yylloc.first_line = strtoul(cp,&cp,10);
904 yylloc.first_line -= 1;
906 cp += strspn(cp, " ");
907 if (*cp == 0) return;
909 char*qt1 = strchr(yytext, '"');
913 char*qt2 = strchr(qt1, '"');
916 char*buf = new char[qt2-qt1+1];
917 strncpy(buf, qt1, qt2-qt1);
920 yylloc.text = set_file_name(buf);
923 extern FILE*vl_input;
927 yylloc.first_line = 1;
929 /* Start the file_names list. From here on, as I get a file
930 name, I will add it to this list. Only add the name if it
931 is not already in the list. */
932 file_names = new struct file_name_cell;
933 file_names->text = strdup(vl_file.c_str());
934 file_names->next = 0;
935 yylloc.text = file_names->text;