Branch data Line data Source code
1 : : /* -*-c-*- */
2 : :
3 : : %{
4 : : /*
5 : : * scan_netlist.l - scanner for the Qucs netlist
6 : : *
7 : : * Copyright (C) 2003-2009 Stefan Jahn <stefan@lkcc.org>
8 : : *
9 : : * This is free software; you can redistribute it and/or modify
10 : : * it under the terms of the GNU General Public License as published by
11 : : * the Free Software Foundation; either version 2, or (at your option)
12 : : * any later version.
13 : : *
14 : : * This software 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.
18 : : *
19 : : * You should have received a copy of the GNU General Public License
20 : : * along with this package; see the file COPYING. If not, write to
21 : : * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
22 : : * Boston, MA 02110-1301, USA.
23 : : *
24 : : * $Id$
25 : : *
26 : : */
27 : :
28 : : #if HAVE_CONFIG_H
29 : : # include <config.h>
30 : : #endif
31 : :
32 : : #include <stdio.h>
33 : : #include <stdlib.h>
34 : : #include <string.h>
35 : : #include <ctype.h>
36 : :
37 : : #ifdef __MINGW32__
38 : : #include <io.h>
39 : : #endif
40 : :
41 : : #ifdef HAVE_UNISTD_H
42 : : #include <unistd.h>
43 : : #endif
44 : :
45 : : #include "logging.h"
46 : : #include "equation.h"
47 : : #include "check_netlist.h"
48 : : #include "tokens_netlist.h"
49 : :
50 : : #if !HAVE_STRCHR
51 : : # define strchr index
52 : : # define strrchr rindex
53 : : #endif
54 : :
55 : : using namespace qucs;
56 : :
57 : 141 : static double netlist_evaluate_scale (double val, char * scale) {
58 : 141 : double factor = 1.0;
59 [ + + ]: 145 : while (isspace (scale[0])) scale++;
60 [ - - - - : 141 : switch (scale[0]) {
- + - - -
- - - - -
- + ]
61 : 0 : case 'E': factor = 1e+18; break;
62 : 0 : case 'P': factor = 1e+15; break;
63 : 0 : case 'T': factor = 1e+12; break;
64 : 0 : case 'G': factor = 1e+09; break;
65 : 0 : case 'M': factor = 1e+06; break;
66 : 3 : case 'k': factor = 1e+03; break;
67 : : case 'm':
68 [ # # ][ # # ]: 0 : if (scale[1] == 'i' && scale[2] == 'l')
69 : 0 : factor = 2.54e-5;
70 : : else
71 : 0 : factor = 1e-03;
72 : 0 : break;
73 : 0 : case 'u': factor = 1e-06; break;
74 : 0 : case 'n': factor = 1e-09; break;
75 : 0 : case 'p': factor = 1e-12; break;
76 : : case 'f':
77 [ # # ]: 0 : if (scale[1] == 't')
78 : 0 : factor = 0.3048;
79 : : else
80 : 0 : factor = 1e-15;
81 : 0 : break;
82 : 0 : case 'a': factor = 1e-18; break;
83 : : case 'd':
84 [ # # ]: 0 : if (scale[1] == 'B') {
85 : 0 : val = std::pow (10.0, val / 10.0);
86 [ # # ]: 0 : if (scale[2] == 'm')
87 : 0 : factor = 1e-03;
88 [ # # ]: 0 : else if (scale[2] == 'u')
89 : 0 : factor = 1e-06;
90 : : }
91 : 0 : break;
92 : : case 'i':
93 [ # # ]: 0 : if (scale[1] == 'n')
94 : 0 : factor = 2.54e-2;
95 : 0 : break;
96 : : case 'y':
97 [ # # ]: 0 : if (scale[1] == 'd')
98 : 0 : factor = 0.9144;
99 : 0 : break;
100 : : }
101 : 141 : return val * factor;
102 : : }
103 : :
104 : : %}
105 : :
106 : : WS [ \t\n\r]
107 : : SIMPLEID [a-zA-Z_][a-zA-Z0-9_]*
108 : : POSTID "."[a-zA-Z0-9_]+
109 : : ID {SIMPLEID}{POSTID}*
110 : : NODE {SIMPLEID}\!?
111 : : FILE "{"[^\t\n\r\}]+"}"
112 : : CHR "'"[^\n\r\']{1}"'"
113 : : STR "'"[^\n\r\']*"'"
114 : : DIGIT [0-9]
115 : : EXPONENT [Ee][+-]?{DIGIT}+
116 : : PFX1 ("E"|"P"|"T"|"G"|"M"|"k"|"m"|"u"|"n"|"p"|"f"|"a")
117 : : PFX2 ("mil"|"in"|"ft"|"yd")
118 : : PFX3 ("dBu"|"dBm"|"dB")
119 : : PFX ({PFX1}|{PFX3})
120 : : UNT ("Ohm"|"S"|"s"|"K"|"H"|"F"|"Hz"|"V"|"A"|"W"|"m")
121 : : EXCEPT ("mm"|{PFX2})
122 : : SU ({PFX}|{UNT}|{PFX}{UNT}|{EXCEPT})
123 : : SPACE [ \t]
124 : : RINT [+-]?{DIGIT}+
125 : : IINT [+-]?[ij]{1}{DIGIT}*
126 : : RFLOAT1 [+-]?{DIGIT}+{EXPONENT}
127 : : RFLOAT2 [+-]?{DIGIT}*"."{DIGIT}+({EXPONENT})?
128 : : IFLOAT1 [+-]?[ij]{1}{DIGIT}+{EXPONENT}
129 : : IFLOAT2 [+-]?[ij]{1}{DIGIT}*"."{DIGIT}+({EXPONENT})?
130 : : CREAL ({RFLOAT1}|{RFLOAT2}|{RINT})
131 : : CIMAG ({IFLOAT1}|{IFLOAT2}|{IINT})
132 : : COMPLEX {CREAL}{CIMAG}
133 : : URINT {DIGIT}+
134 : : UIINT [ij]{1}{DIGIT}*
135 : : URFLOAT1 {DIGIT}+{EXPONENT}
136 : : URFLOAT2 {DIGIT}*"."{DIGIT}+({EXPONENT})?
137 : : UIFLOAT1 [ij]{1}{DIGIT}+{EXPONENT}
138 : : UIFLOAT2 [ij]{1}{DIGIT}*"."{DIGIT}+({EXPONENT})?
139 : : UCREAL ({URFLOAT1}|{URFLOAT2}|{URINT})({SPACE})*({PFX})?
140 : : UCIMAG ({UIFLOAT1}|{UIFLOAT2}|{UIINT})({SPACE})*({PFX})?
141 : : UCOMPLEX {UCREAL}{UCIMAG}
142 : :
143 : :
144 : : %x COMMENT STR EQN
145 : : %option yylineno noyywrap nounput prefix="netlist_"
146 : :
147 : : %%
148 : :
149 : : <INITIAL,STR>{SU} { /* identify scale and/or unit */
150 : 1679 : netlist_lval.str = strdup (netlist_text);
151 : 1679 : return ScaleOrUnit;
152 : : }
153 : : <INITIAL>"Eqn" { /* special equation case */
154 : 68 : BEGIN(EQN);
155 : 68 : return Eqn;
156 : : }
157 : : <INITIAL>"."{SPACE}*"Def"{SPACE}*":" {
158 : : /* subcircuit definition begins */
159 : 13 : return DefSub;
160 : : }
161 : : <INITIAL>"."{SPACE}*"Def"{SPACE}*":"{SPACE}*"End" {
162 : : /* subcircuit definition ends */
163 : 13 : return EndSub;
164 : : }
165 : : <INITIAL,STR>{ID} { /* identify identifier */
166 : 5219 : netlist_lval.ident = strdup (netlist_text);
167 : 5219 : return Identifier;
168 : : }
169 : : <INITIAL>{NODE} { /* identify node identifier */
170 : 0 : netlist_lval.ident = strdup (netlist_text);
171 : 0 : return Identifier;
172 : : }
173 : : <INITIAL,STR>{FILE} { /* identify file reference */
174 : 0 : char * p = strrchr (netlist_text, '}'); *p = '\0';
175 : 0 : netlist_lval.ident = strdup (&netlist_text[1]);
176 : 0 : return Identifier;
177 : : }
178 : : <INITIAL,STR>{CREAL} { /* identify (signed) real float */
179 : 9232 : netlist_lval.d = strtod (netlist_text, NULL);
180 : 9232 : return REAL;
181 : : }
182 : : <INITIAL,STR>{CIMAG} { /* identify (signed) imaginary float */
183 [ # # ][ # # ]: 0 : if (netlist_text[0] == 'i' || netlist_text[0] == 'j')
184 [ # # ]: 0 : netlist_text[0] = (netlist_text[1] == '\0') ? '1' : '0';
185 : : else
186 : 0 : netlist_text[1] = '0';
187 : 0 : netlist_lval.d = strtod (netlist_text, NULL);
188 : 0 : return IMAG;
189 : : }
190 : : <INITIAL,STR>{COMPLEX} { /* identify complete (signed) complex number */
191 : 0 : int i = 0;
192 [ # # ][ # # ]: 0 : while (netlist_text[i] != 'i' && netlist_text[i] != 'j') i++;
[ # # ]
193 : 0 : netlist_text[i] = netlist_text[i - 1];
194 : 0 : netlist_text[i - 1] = '\0';
195 : 0 : netlist_lval.c.r = strtod (netlist_text, NULL);
196 : 0 : netlist_lval.c.i = strtod (&netlist_text[i], NULL);
197 : 0 : return COMPLEX;
198 : : }
199 : : <INITIAL,EQN>{ID}{SPACE}*=[^=] { /* identify 'identifier =' assign */
200 : 10506 : int len = netlist_leng - 3;
201 [ - + ]: 10506 : while (isspace (netlist_text[len])) len--;
202 : 10506 : netlist_lval.ident = (char *) calloc (len + 2, 1);
203 : 10506 : memcpy (netlist_lval.ident, netlist_text, len + 1);
204 [ - + ][ + + ]: 21012 : yyless (netlist_leng - 1); /* push back last character */
205 : 10506 : return Assign;
206 : : }
207 : :
208 : 6 : <INITIAL,STR>"[" { /* special token for the value list */ return '['; }
209 : 6 : <INITIAL,STR>"]" { /* special token for the value list */ return ']'; }
210 : 12 : <INITIAL,STR>";" { /* special token for the value list */ return ';'; }
211 : :
212 : 181 : <INITIAL>"." { /* pass the '.' to the parser */ return '.'; }
213 : 1085 : <INITIAL>":" { /* pass the ':' to the parser */ return ':'; }
214 : 0 : <INITIAL>"=" { /* pass the '=' to the parser */ return '='; }
215 : 1232 : <INITIAL>\r?\n { /* detect end of line */ return Eol; }
216 : :
217 : : <INITIAL,EQN>{SPACE}|\\\r?\n /* skip spaces and the trailing '\' */
218 : 12782 :
219 : : <INITIAL>"#" { /* leave these characters */
220 : 103 : BEGIN(COMMENT);
221 : : }
222 : 103 : <INITIAL>\" { /* string constant starts here */
223 : 10299 : BEGIN(STR);
224 : 10299 : return '"';
225 : : }
226 : : <INITIAL>. { /* any other character in invalid */
227 : : logprint (LOG_ERROR,
228 : : "line %d: syntax error, unrecognized character: `%s'\n",
229 : 0 : netlist_lineno, netlist_text);
230 : 0 : return InvalidCharacter;
231 : : }
232 : :
233 : : <COMMENT>. { /* skip any character in here */ }
234 : 8580 : <COMMENT>\r?\n { BEGIN(INITIAL); /* skipping ends here */ }
235 : 103 :
236 : : <STR>\" { /* string constant ends here */
237 : 10299 : BEGIN(INITIAL);
238 : 10299 : return '"';
239 : : }
240 : : <STR>\r?\n { /* string in a single line only */
241 : : logprint (LOG_ERROR,
242 : : "line %d: syntax error, unterminated string constant\n",
243 : 0 : netlist_lineno);
244 : 0 : return Eol;
245 : : }
246 : : <STR,EQN>{SPACE} /* skip spaces */
247 : 1329 :
248 : : <STR>. { /* any other character is invalid */
249 : : logprint (LOG_ERROR,
250 : : "line %d: syntax error, unrecognized character: `%s'\n",
251 : 0 : netlist_lineno, netlist_text);
252 : 0 : return InvalidCharacter;
253 : : }
254 : :
255 : : <EQN>[-+*/%(),^:\"\[\]\?] { /* return operators unchanged */
256 : 950 : return netlist_text[0];
257 : : }
258 : :
259 : 0 : <EQN>">=" { return GreaterOrEqual; }
260 : 0 : <EQN>"<=" { return LessOrEqual; }
261 : 0 : <EQN>"!=" { return NotEqual; }
262 : 0 : <EQN>"==" { return Equal; }
263 : 0 : <EQN>"&&" { return And; }
264 : 0 : <EQN>"||" { return Or; }
265 : 21 : <EQN>"<" { return Less; }
266 : 0 : <EQN>">" { return Greater; }
267 : 0 : <EQN>"!" { return Not; }
268 : :
269 : : <EQN>[,;] { /* special tokens for vectors / matrices */
270 : 0 : return netlist_text[0];
271 : : }
272 : :
273 : : <EQN>{UCREAL} { /* identify unsigned real float */
274 : 141 : char * endptr = NULL;
275 : 141 : netlist_lval.d = strtod (netlist_text, &endptr);
276 [ + - ]: 141 : netlist_lval.d = netlist_evaluate_scale (netlist_lval.d, endptr);
277 : 141 : return REAL;
278 : : }
279 : : <EQN>{UCIMAG} { /* identify unsigned imaginary float */
280 [ # # ][ # # ]: 0 : if (netlist_text[0] == 'i' || netlist_text[0] == 'j')
281 [ # # ]: 0 : netlist_text[0] = (netlist_text[1] == '\0') ? '1' : '0';
282 : : else
283 : 0 : netlist_text[1] = '0';
284 : 0 : char * endptr = NULL;
285 : 0 : netlist_lval.d = strtod (netlist_text, &endptr);
286 [ # # ]: 0 : netlist_lval.d = netlist_evaluate_scale (netlist_lval.d, endptr);
287 : 0 : return IMAG;
288 : : }
289 : : <EQN>{ID} { /* identify identifier */
290 : 442 : netlist_lval.ident = strdup (netlist_text);
291 : 442 : return Identifier;
292 : : }
293 : : <EQN>{CHR} {
294 : 0 : netlist_lval.chr = netlist_text[1];
295 : 0 : return Character;
296 : : }
297 : : <EQN>{STR} {
298 : 0 : netlist_lval.str = strdup (&netlist_text[1]);
299 : 0 : netlist_lval.str[strlen (netlist_lval.str) - 1] = '\0';
300 : 0 : return STRING;
301 : : }
302 : 68 : <EQN>\r?\n { /* detect end of line */ BEGIN(INITIAL); return Eol; }
303 : :
304 : : <EQN>. { /* any other character in invalid */
305 : : logprint (LOG_ERROR,
306 : : "line %d: syntax error, unrecognized character: `%s'\n",
307 : 0 : netlist_lineno, netlist_text);
308 : 0 : return InvalidCharacter;
309 : : }
310 : :
311 : 0 : %%
|