1 %option prefix="sdf"
2 %option never-interactive
3 %option nounput
4 %option noinput
5
6 %{
7 /*
8 * Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com)
9 *
10 * This source code is free software; you can redistribute it
11 * and/or modify it in source code form under the terms of the GNU
12 * General Public License as published by the Free Software
13 * Foundation; either version 2 of the License, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25
26 # include "sdf_priv.h"
27 # include "sdf_parse_priv.h"
28 # include "sdf_parse.h"
29 # include <stdlib.h>
30 # include <string.h>
31 # include <strings.h>
32 # include <assert.h>
33
34 static void process_quoted_string(void);
35 static int lookup_keyword(const char*text);
36 const char*sdf_parse_path = 0;
37
yywrap(void)38 static int yywrap(void)
39 {
40 return 1;
41 }
42
43
44 # define yylval sdflval
45 %}
46
47 %x CCOMMENT
48 %x COND_EDGE_ID
49 %x EDGE_ID
50
51 %%
52
53 /* Skip C++-style comments. */
54 "//".* { ; }
55
56 /* Skip C-style comments. */
57 "/*" { BEGIN(CCOMMENT); }
58 <CCOMMENT>. { ; }
59 <CCOMMENT>\n { sdflloc.first_line += 1; }
60 <CCOMMENT>"*/" { BEGIN(0); }
61
62 [ \m\t] { /* Skip white space. */; }
63
64 /* Count lines so that the parser can assign line numbers. */
65 \n { sdflloc.first_line += 1; }
66
67 /* The other edge identifiers. */
68 <COND_EDGE_ID,EDGE_ID>"01" {return K_01; }
69 <COND_EDGE_ID,EDGE_ID>"10" {return K_10; }
70 <COND_EDGE_ID,EDGE_ID>"0"[zZ] {return K_0Z; }
71 <COND_EDGE_ID,EDGE_ID>[zZ]"1" {return K_Z1; }
72 <COND_EDGE_ID,EDGE_ID>"1"[zZ] {return K_1Z; }
73 <COND_EDGE_ID,EDGE_ID>[zZ]"0" {return K_Z0; }
74 <COND_EDGE_ID,EDGE_ID>[pP][oO][sS][eE][dD][gG][eE] {return K_POSEDGE; }
75 <COND_EDGE_ID,EDGE_ID>[nN][eE][gG][eE][dD][gG][eE] {return K_NEGEDGE; }
76 <COND_EDGE_ID>[cC][oO][nN][dD] {return K_COND; }
77
78 /* Integer values */
79 [0-9]+ {
80 yylval.int_val = strtoul(yytext, 0, 10);
81 return INTEGER;
82 }
83
84 /* Real values */
85 [0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)? {
86 yylval.real_val = strtod(yytext, 0);
87 return REAL_NUMBER;
88 }
89
90 ([a-zA-Z_]|(\\[^ \t\b\f\r\n]))([a-zA-Z0-9$_]|(\\[^ \t\b\f\r\n]))* {
91 return lookup_keyword(yytext);
92 }
93
94 \"[^\"]*\" {
95 process_quoted_string();
96 return QSTRING;
97 }
98
99 /* Scalar constants. */
100 ("1"?"'"[bB])?"0" { return K_LOGICAL_ZERO; }
101 ("1"?"'"[bB])?"1" { return K_LOGICAL_ONE; }
102
103 /* Equality operators. */
104
105 "==" { return K_EQ; }
106 "!=" { return K_NE; }
107 "===" { return K_CEQ; }
108 "!==" { return K_CNE; }
109
110 /* Other operators. */
111
112 "&&" { return K_LAND; }
113 "||" { return K_LOR; }
114
115 /* The HCHAR (hierarchy separator) is set by the SDF file itself. We
116 recognize here the HCHAR. */
117 [./] {
118 if (sdf_use_hchar==yytext[0])
119 return HCHAR;
120 else
121 return yytext[0];
122 }
123
124 . { return yytext[0]; }
125
126 %%
127
128 static struct {
129 const char*name;
130 int code;
131 } keywords[] = {
132 { "ABSOLUTE", K_ABSOLUTE },
133 { "CELL", K_CELL },
134 { "CELLTYPE", K_CELLTYPE },
135 { "DATE", K_DATE },
136 { "COND", K_COND },
137 { "CONDELSE", K_CONDELSE },
138 { "DELAY", K_DELAY },
139 { "DELAYFILE", K_DELAYFILE },
140 { "DESIGN", K_DESIGN },
141 { "DIVIDER", K_DIVIDER },
142 { "HOLD", K_HOLD },
143 { "INCREMENT", K_INCREMENT },
144 { "INTERCONNECT", K_INTERCONNECT },
145 { "INSTANCE", K_INSTANCE },
146 { "IOPATH", K_IOPATH },
147 { "PATHPULSE", K_PATHPULSE },
148 { "PATHPULSEPERCENT", K_PATHPULSEPERCENT },
149 { "PERIOD", K_PERIOD },
150 { "PROCESS", K_PROCESS },
151 { "PROGRAM", K_PROGRAM },
152 { "RECREM", K_RECREM },
153 { "RECOVERY", K_RECOVERY },
154 { "REMOVAL", K_REMOVAL },
155 { "SDFVERSION", K_SDFVERSION },
156 { "SETUP", K_SETUP },
157 { "SETUPHOLD", K_SETUPHOLD },
158 { "TEMPERATURE", K_TEMPERATURE },
159 { "TIMESCALE", K_TIMESCALE },
160 { "TIMINGCHECK", K_TIMINGCHECK },
161 { "VENDOR", K_VENDOR },
162 { "VERSION", K_VERSION },
163 { "VOLTAGE", K_VOLTAGE },
164 { "WIDTH", K_WIDTH },
165 { 0, IDENTIFIER }
166 };
167
start_edge_id(unsigned cond)168 void start_edge_id(unsigned cond)
169 {
170 if (cond) BEGIN(COND_EDGE_ID);
171 else BEGIN(EDGE_ID);
172 }
173
stop_edge_id(void)174 void stop_edge_id(void)
175 {
176 BEGIN(0);
177 }
178
lookup_keyword(const char * text)179 static int lookup_keyword(const char*text)
180 {
181 unsigned idx, len, skip;
182 for (idx = 0 ; keywords[idx].name ; idx += 1) {
183 if (strcasecmp(text, keywords[idx].name) == 0)
184 return keywords[idx].code;
185 }
186
187 /* Process any escaped characters. */
188 skip = 0;
189 len = strlen(yytext);
190 for (idx = 0; idx < len; idx += 1) {
191 if (yytext[idx] == '\\') {
192 skip += 1;
193 idx += 1;
194 }
195 yytext[idx-skip] = yytext[idx];
196 }
197 yytext[idx-skip] = 0;
198
199 yylval.string_val = strdup(yytext);
200 return IDENTIFIER;
201 }
202
203 /*
204 * Create a string without the leading and trailing quotes.
205 */
process_quoted_string(void)206 static void process_quoted_string(void)
207 {
208 char*endp;
209
210 yylval.string_val = strdup(yytext+1);
211 endp = yylval.string_val+strlen(yylval.string_val);
212 assert(endp[-1] == '"');
213 endp[-1] = 0;
214 }
215
216 /*
217 * Modern version of flex (>=2.5.9) can clean up the scanner data.
218 */
destroy_sdf_lexor(void)219 static void destroy_sdf_lexor(void)
220 {
221 # ifdef FLEX_SCANNER
222 # if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
223 # if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
224 yylex_destroy();
225 # endif
226 # endif
227 # endif
228 }
229
230 extern int sdfparse(void);
sdf_process_file(FILE * fd,const char * path)231 void sdf_process_file(FILE*fd, const char*path)
232 {
233 yyrestart(fd);
234
235 sdf_parse_path = path;
236 sdfparse();
237 destroy_sdf_lexor();
238 sdf_parse_path = 0;
239 }
240