Qucs-core
0.0.19
|
00001 /* -*-c-*- */ 00002 00003 %{ 00004 /* 00005 * scan_netlist.l - scanner for the Qucs netlist 00006 * 00007 * Copyright (C) 2003-2009 Stefan Jahn <stefan@lkcc.org> 00008 * 00009 * This is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2, or (at your option) 00012 * any later version. 00013 * 00014 * This software is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this package; see the file COPYING. If not, write to 00021 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00022 * Boston, MA 02110-1301, USA. 00023 * 00024 * $Id$ 00025 * 00026 */ 00027 00028 #if defined(__clang__) 00029 #pragma clang diagnostic push 00030 #pragma clang diagnostic ignored "-Wdeprecated-register" 00031 #endif 00032 00033 #if HAVE_CONFIG_H 00034 # include <config.h> 00035 #endif 00036 00037 #include <stdio.h> 00038 #include <stdlib.h> 00039 #include <string.h> 00040 #include <ctype.h> 00041 00042 #ifdef __MINGW32__ 00043 #include <io.h> 00044 #endif 00045 00046 #ifdef HAVE_UNISTD_H 00047 #include <unistd.h> 00048 #endif 00049 00050 #include "logging.h" 00051 #include "equation.h" 00052 #include "check_netlist.h" 00053 #include "tokens_netlist.h" 00054 00055 #if !HAVE_STRCHR 00056 # define strchr index 00057 # define strrchr rindex 00058 #endif 00059 00060 using namespace qucs; 00061 00062 static double netlist_evaluate_scale (double val, char * scale) { 00063 double factor = 1.0; 00064 while (isspace (scale[0])) scale++; 00065 switch (scale[0]) { 00066 case 'E': factor = 1e+18; break; 00067 case 'P': factor = 1e+15; break; 00068 case 'T': factor = 1e+12; break; 00069 case 'G': factor = 1e+09; break; 00070 case 'M': factor = 1e+06; break; 00071 case 'k': factor = 1e+03; break; 00072 case 'm': 00073 if (scale[1] == 'i' && scale[2] == 'l') 00074 factor = 2.54e-5; 00075 else 00076 factor = 1e-03; 00077 break; 00078 case 'u': factor = 1e-06; break; 00079 case 'n': factor = 1e-09; break; 00080 case 'p': factor = 1e-12; break; 00081 case 'f': 00082 if (scale[1] == 't') 00083 factor = 0.3048; 00084 else 00085 factor = 1e-15; 00086 break; 00087 case 'a': factor = 1e-18; break; 00088 case 'd': 00089 if (scale[1] == 'B') { 00090 val = std::pow (10.0, val / 10.0); 00091 if (scale[2] == 'm') 00092 factor = 1e-03; 00093 else if (scale[2] == 'u') 00094 factor = 1e-06; 00095 } 00096 break; 00097 case 'i': 00098 if (scale[1] == 'n') 00099 factor = 2.54e-2; 00100 break; 00101 case 'y': 00102 if (scale[1] == 'd') 00103 factor = 0.9144; 00104 break; 00105 } 00106 return val * factor; 00107 } 00108 00109 %} 00110 00111 WS [ \t\n\r] 00112 SIMPLEID [a-zA-Z_][a-zA-Z0-9_]* 00113 POSTID "."[a-zA-Z0-9_]+ 00114 ID {SIMPLEID}{POSTID}* 00115 NODE {SIMPLEID}\!? 00116 FILE "{"[^\t\n\r\}]+"}" 00117 CHR "'"[^\n\r\']{1}"'" 00118 STR "'"[^\n\r\']*"'" 00119 DIGIT [0-9] 00120 EXPONENT [Ee][+-]?{DIGIT}+ 00121 PFX1 ("E"|"P"|"T"|"G"|"M"|"k"|"m"|"u"|"n"|"p"|"f"|"a") 00122 PFX2 ("mil"|"in"|"ft"|"yd") 00123 PFX3 ("dBu"|"dBm"|"dB") 00124 PFX ({PFX1}|{PFX3}) 00125 UNT ("Ohm"|"S"|"s"|"K"|"H"|"F"|"Hz"|"V"|"A"|"W"|"m") 00126 EXCEPT ("mm"|{PFX2}) 00127 SU ({PFX}|{UNT}|{PFX}{UNT}|{EXCEPT}) 00128 SPACE [ \t] 00129 RINT [+-]?{DIGIT}+ 00130 IINT [+-]?[ij]{1}{DIGIT}* 00131 RFLOAT1 [+-]?{DIGIT}+{EXPONENT} 00132 RFLOAT2 [+-]?{DIGIT}*"."{DIGIT}+({EXPONENT})? 00133 IFLOAT1 [+-]?[ij]{1}{DIGIT}+{EXPONENT} 00134 IFLOAT2 [+-]?[ij]{1}{DIGIT}*"."{DIGIT}+({EXPONENT})? 00135 CREAL ({RFLOAT1}|{RFLOAT2}|{RINT}) 00136 CIMAG ({IFLOAT1}|{IFLOAT2}|{IINT}) 00137 COMPLEX {CREAL}{CIMAG} 00138 URINT {DIGIT}+ 00139 UIINT [ij]{1}{DIGIT}* 00140 URFLOAT1 {DIGIT}+{EXPONENT} 00141 URFLOAT2 {DIGIT}*"."{DIGIT}+({EXPONENT})? 00142 UIFLOAT1 [ij]{1}{DIGIT}+{EXPONENT} 00143 UIFLOAT2 [ij]{1}{DIGIT}*"."{DIGIT}+({EXPONENT})? 00144 UCREAL ({URFLOAT1}|{URFLOAT2}|{URINT})({SPACE})*({PFX})? 00145 UCIMAG ({UIFLOAT1}|{UIFLOAT2}|{UIINT})({SPACE})*({PFX})? 00146 UCOMPLEX {UCREAL}{UCIMAG} 00147 00148 00149 %x COMMENT STR EQN 00150 %option yylineno noyywrap nounput noinput prefix="netlist_" 00151 00152 %% 00153 00154 <INITIAL,STR>{SU} { /* identify scale and/or unit */ 00155 netlist_lval.str = strdup (netlist_text); 00156 return ScaleOrUnit; 00157 } 00158 <INITIAL>"Eqn" { /* special equation case */ 00159 BEGIN(EQN); 00160 return Eqn; 00161 } 00162 <INITIAL>"."{SPACE}*"Def"{SPACE}*":" { 00163 /* subcircuit definition begins */ 00164 return DefSub; 00165 } 00166 <INITIAL>"."{SPACE}*"Def"{SPACE}*":"{SPACE}*"End" { 00167 /* subcircuit definition ends */ 00168 return EndSub; 00169 } 00170 <INITIAL,STR>{ID} { /* identify identifier */ 00171 netlist_lval.ident = strdup (netlist_text); 00172 return Identifier; 00173 } 00174 <INITIAL>{NODE} { /* identify node identifier */ 00175 netlist_lval.ident = strdup (netlist_text); 00176 return Identifier; 00177 } 00178 <INITIAL,STR>{FILE} { /* identify file reference */ 00179 char * p = strrchr (netlist_text, '}'); 00180 if (!p) { 00181 return InvalidCharacter; 00182 } 00183 //size_t len = (size_t)p - (size_t)&netlist_text[1]; 00184 //netlist_lval.ident = strndup (&netlist_text[1], len); 00185 *p = '\0'; 00186 netlist_lval.ident = strdup (&netlist_text[1]); 00187 return Identifier; 00188 } 00189 <INITIAL,STR>{CREAL} { /* identify (signed) real float */ 00190 netlist_lval.d = strtod (netlist_text, NULL); 00191 return REAL; 00192 } 00193 <INITIAL,STR>{CIMAG} { /* identify (signed) imaginary float */ 00194 if (netlist_text[0] == 'i' || netlist_text[0] == 'j') 00195 netlist_text[0] = (netlist_text[1] == '\0') ? '1' : '0'; 00196 else 00197 netlist_text[1] = '0'; 00198 netlist_lval.d = strtod (netlist_text, NULL); 00199 return IMAG; 00200 } 00201 <INITIAL,STR>{COMPLEX} { /* identify complete (signed) complex number */ 00202 int i = 0; 00203 while (netlist_text[i] != 'i' && netlist_text[i] != 'j') i++; 00204 netlist_text[i] = netlist_text[i - 1]; 00205 netlist_text[i - 1] = '\0'; 00206 netlist_lval.c.r = strtod (netlist_text, NULL); 00207 netlist_lval.c.i = strtod (&netlist_text[i], NULL); 00208 return COMPLEX; 00209 } 00210 <INITIAL,EQN>{ID}{SPACE}*=[^=] { /* identify 'identifier =' assign */ 00211 int len = netlist_leng - 3; 00212 while (isspace (netlist_text[len])) len--; 00213 netlist_lval.ident = (char *) calloc (len + 2, 1); 00214 memcpy (netlist_lval.ident, netlist_text, len + 1); 00215 yyless (netlist_leng - 1); /* push back last character */ 00216 return Assign; 00217 } 00218 00219 <INITIAL,STR>"[" { /* special token for the value list */ return '['; } 00220 <INITIAL,STR>"]" { /* special token for the value list */ return ']'; } 00221 <INITIAL,STR>";" { /* special token for the value list */ return ';'; } 00222 00223 <INITIAL>"." { /* pass the '.' to the parser */ return '.'; } 00224 <INITIAL>":" { /* pass the ':' to the parser */ return ':'; } 00225 <INITIAL>"=" { /* pass the '=' to the parser */ return '='; } 00226 <INITIAL>\r?\n { /* detect end of line */ return Eol; } 00227 00228 <INITIAL,EQN>{SPACE}|\\\r?\n /* skip spaces and the trailing '\' */ 00229 00230 <INITIAL>"#" { /* leave these characters */ 00231 BEGIN(COMMENT); 00232 } 00233 <INITIAL>\" { /* string constant starts here */ 00234 BEGIN(STR); 00235 return '"'; 00236 } 00237 <INITIAL>. { /* any other character in invalid */ 00238 logprint (LOG_ERROR, 00239 "line %d: syntax error, unrecognized character: `%s'\n", 00240 netlist_lineno, netlist_text); 00241 return InvalidCharacter; 00242 } 00243 00244 <COMMENT>. { /* skip any character in here */ } 00245 <COMMENT>\r?\n { BEGIN(INITIAL); /* skipping ends here */ } 00246 00247 <STR>\" { /* string constant ends here */ 00248 BEGIN(INITIAL); 00249 return '"'; 00250 } 00251 <STR>\r?\n { /* string in a single line only */ 00252 logprint (LOG_ERROR, 00253 "line %d: syntax error, unterminated string constant\n", 00254 netlist_lineno); 00255 return Eol; 00256 } 00257 <STR,EQN>{SPACE} /* skip spaces */ 00258 00259 <STR>. { /* any other character is invalid */ 00260 logprint (LOG_ERROR, 00261 "line %d: syntax error, unrecognized character: `%s'\n", 00262 netlist_lineno, netlist_text); 00263 return InvalidCharacter; 00264 } 00265 00266 <EQN>[-+*/%(),^:\"\[\]\?] { /* return operators unchanged */ 00267 return netlist_text[0]; 00268 } 00269 00270 <EQN>">=" { return GreaterOrEqual; } 00271 <EQN>"<=" { return LessOrEqual; } 00272 <EQN>"!=" { return NotEqual; } 00273 <EQN>"==" { return Equal; } 00274 <EQN>"&&" { return And; } 00275 <EQN>"||" { return Or; } 00276 <EQN>"<" { return Less; } 00277 <EQN>">" { return Greater; } 00278 <EQN>"!" { return Not; } 00279 00280 <EQN>[,;] { /* special tokens for vectors / matrices */ 00281 return netlist_text[0]; 00282 } 00283 00284 <EQN>{UCREAL} { /* identify unsigned real float */ 00285 char * endptr = NULL; 00286 netlist_lval.d = strtod (netlist_text, &endptr); 00287 netlist_lval.d = netlist_evaluate_scale (netlist_lval.d, endptr); 00288 return REAL; 00289 } 00290 <EQN>{UCIMAG} { /* identify unsigned imaginary float */ 00291 if (netlist_text[0] == 'i' || netlist_text[0] == 'j') 00292 netlist_text[0] = (netlist_text[1] == '\0') ? '1' : '0'; 00293 else 00294 netlist_text[1] = '0'; 00295 char * endptr = NULL; 00296 netlist_lval.d = strtod (netlist_text, &endptr); 00297 netlist_lval.d = netlist_evaluate_scale (netlist_lval.d, endptr); 00298 return IMAG; 00299 } 00300 <EQN>{ID} { /* identify identifier */ 00301 netlist_lval.ident = strdup (netlist_text); 00302 return Identifier; 00303 } 00304 <EQN>{CHR} { 00305 netlist_lval.chr = netlist_text[1]; 00306 return Character; 00307 } 00308 <EQN>{STR} { 00309 netlist_lval.str = strdup (&netlist_text[1]); 00310 netlist_lval.str[strlen (netlist_lval.str) - 1] = '\0'; 00311 return STRING; 00312 } 00313 <EQN>\r?\n { /* detect end of line */ BEGIN(INITIAL); return Eol; } 00314 00315 <EQN>. { /* any other character in invalid */ 00316 logprint (LOG_ERROR, 00317 "line %d: syntax error, unrecognized character: `%s'\n", 00318 netlist_lineno, netlist_text); 00319 return InvalidCharacter; 00320 } 00321 00322 %%