Qucs-core  0.0.19
parse_spice.y
Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 
00003 %{
00004 /*
00005  * parse_spice.y - parser for a Spice netlist
00006  *
00007  * Copyright (C) 2004, 2005, 2006, 2007, 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 HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <ctype.h>
00036 
00037 #if defined(_WIN32) & not defined(__MINGW32__)
00038 #define strcasecmp stricmp
00039 #endif
00040 
00041 #define YYERROR_VERBOSE 42
00042 #define YYDEBUG 1
00043 #define YYMAXDEPTH 1000000
00044 
00045 #include "check_spice.h"
00046 
00047 // Converts the given string into upper case.
00048 static char * spice_toupper (char * str) {
00049   for (unsigned int i = 0; i < strlen (str); i++) {
00050     if (str[i] >= 'a' && str[i] <= 'z') str[i] = toupper (str[i]);
00051   }
00052   return str;
00053 }
00054 
00055 // Creates a device instance.
00056 static struct definition_t * spice_create_device (char * instance) {
00057   struct definition_t * def = create_definition ();
00058   def->action = PROP_COMPONENT;
00059   def->instance = spice_toupper (instance);
00060   def->type = (char *) calloc (2, 1);
00061   def->type[0] = def->instance[0];
00062   def->line = spice_lineno;
00063   return def;
00064 }
00065 
00066 // Creates an action instance.
00067 static struct definition_t * spice_create_action (char * type,
00068                                                   char * instance) {
00069   struct definition_t * def = create_definition ();
00070   def->action = PROP_ACTION;
00071   def->instance = spice_toupper (instance);
00072   def->type = spice_toupper (type);
00073   def->line = spice_lineno;
00074   return def;
00075 }
00076 
00077 // Create a string value.
00078 static struct value_t * spice_create_str_value (char * value, int hint) {
00079   struct value_t * val = create_value ();
00080   val->ident = spice_toupper (value);
00081   val->hint |= hint;
00082   return val;
00083 }
00084 
00085 // Create a real value.
00086 static struct value_t * spice_create_val_value (char * value, int hint) {
00087   struct value_t * val = create_value ();
00088   val->ident = value;
00089   val->value = strtod (value, NULL);
00090   val->hint |= hint;
00091   return val;
00092 }
00093 
00094 // Create a key/value pair.
00095 static struct value_t * spice_create_par_value (char * key, char * value) {
00096   struct value_t * val = spice_create_str_value (key, HINT_PAIR);
00097   val->unit = value;
00098   return val;
00099 }
00100 
00101 // Append a string value to the definition.
00102 static void spice_append_str_value (struct definition_t * def,
00103                                     char * value, int hint) {
00104   struct value_t * val = spice_create_str_value (value, hint);
00105   def->values = netlist_append_values (def->values, val);
00106 }
00107 
00108 // Append a string value to the given values.
00109 static struct value_t * spice_append_str_values (struct value_t * values,
00110                                                  char * value, int hint) {
00111   struct value_t * val = spice_create_str_value (value, hint);
00112   return netlist_append_values (values, val);
00113 }
00114 
00115 // Append a real value to the definition.
00116 static void spice_append_val_value (struct definition_t * def,
00117                                     char * value, int hint) {
00118   struct value_t * val = spice_create_val_value (value, hint);
00119   def->values = netlist_append_values (def->values, val);
00120 }
00121 
00122 // Append a real value to the given values.
00123 static struct value_t * spice_append_val_values (struct value_t * values,
00124                                                  char * value, int hint) {
00125   struct value_t * val = spice_create_val_value (value, hint);
00126   return netlist_append_values (values, val);
00127 }
00128 
00129 %}
00130 
00131 %name-prefix "spice_"
00132 
00133 %token TitleLine InvalidCharacter End Eol
00134 %token Identifier Digits Floats Nodes Options Function
00135 %token SUBCKT_Action ENDS_Action AC_Action OP_Action I_Source SAVE_Action
00136 %token RLC_Device L_Device K_Device IV_Source GE_Source FH_Source V_Source
00137 %token Diode_Device Bipolar_Device JFET_Device MOSFET_Device MESFET_Device
00138 %token MODEL_Action MODEL_Spec TRAN_Action PLOT_Action VoltFunc CurrFunc
00139 %token DC_Action PRINT_Action OPTIONS_Action WIDTH_Action NOISE_Action
00140 %token PZ_Action CurVol PoleZero ALL_Special X_Device O_Device ModelProps
00141 %token OFF_Special IC_Special SIM_Type TEMP_Special MOS_Special B_Source
00142 %token DISTO_Action INCLUDE_Action File BranchFunc NODESET_Action T_Device
00143 %token U_Device S_Device W_Device ON_Special TF_Action SENS_Action FOUR_Action
00144 %token OpFunc Behave TC_Special TEMP_Action
00145 
00146 %union {
00147   char * ident;
00148   char * str;
00149   double d;
00150   struct definition_t * definition;
00151   struct definition_t * subcircuit;
00152   struct value_t * value;
00153 }
00154 
00155 %type <str> TitleLine
00156 %type <definition> DefinitionLine BeginSub SubBody Subcircuit SubBodyLine
00157 
00158 %type <value> NodeList PairList Expr DC_List ValueList ExprList PLOT_List
00159 %type <value> VOLTAGE_Output CURRENT_Output Output_Range PRINT_List
00160 %type <value> OPTIONS_List MODEL_List DEVICE_List_1 DEVICE_List_2 DEVICE_List_3
00161 %type <value> IC_Condition_1 IC_Condition_2 IC_Condition_3 NODESET_List
00162 %type <value> IC_Condition_4 SWITCH_State NodeValueList TC_Value_1 TC_Value_2
00163 %type <value> VSourceList
00164 
00165 %type <ident> Identifier Nodes Function Value Floats Digits Node FH_Node
00166 %type <ident> RLC_Device K_Device L_Device IV_Source GE_Source FH_Source
00167 %type <ident> V_Source MODEL_Spec Diode_Device Bipolar_Device JFET_Device
00168 %type <ident> MOSFET_Device MESFET_Device TRAN_Action PLOT_Action MODEL_Action
00169 %type <ident> VoltFunc CurrFunc AC_Action DC_Action B_Source DISTO_Action
00170 %type <ident> PRINT_Action Options OPTIONS_Action WIDTH_Action INCLUDE_Action
00171 %type <ident> NOISE_Action PZ_Action CurVol PoleZero ALL_Special File
00172 %type <ident> X_Device SUBCKT_Action SubCkt_Ident O_Device MODEL_Ident
00173 %type <ident> ModelProps OP_Action I_Source IV_Reference SAVE_Action ON_Special
00174 %type <ident> IC_Special OFF_Special SIM_Type TEMP_Special MOS_Special
00175 %type <ident> BranchFunc NODESET_Action T_Device U_Device S_Device W_Device
00176 %type <ident> TF_Action SENS_Action FOUR_Action OpFunc TC_Special TEMP_Action
00177 %type <ident> Behave
00178 
00179 %%
00180 
00181 Input:
00182   InputList End {
00183   }
00184   | TitleLine InputList End {
00185     spice_title = $1;
00186   }
00187   | InputList {
00188     fprintf (stderr, "spice notice, no .END directive found, continuing\n");
00189   }
00190   | TitleLine InputList {
00191     spice_title = $1;
00192     fprintf (stderr, "spice notice, no .END directive found, continuing\n");
00193   }
00194 ;
00195 
00196 InputList: /* nothing */
00197   | InputLine InputList
00198 ;
00199 
00200 InputLine:
00201   Subcircuit {
00202     /* chain definition root */
00203     $1->next = definition_root;
00204     definition_root = $1;
00205   }
00206   | DefinitionLine {
00207     /* chain definition root */
00208     if ($1) {
00209       $1->next = definition_root;
00210       definition_root = $1;
00211     }
00212   }
00213   | Eol { /* nothing to do here */ }
00214 ;
00215 
00216 DefinitionLine:
00217   RLC_Device Node Node Value PairList Eol {
00218     /* R, L and C definitions */
00219     $$ = spice_create_device ($1);
00220     spice_append_str_value ($$, $2, HINT_NODE);
00221     spice_append_str_value ($$, $3, HINT_NODE);
00222     spice_append_val_value ($$, $4, HINT_NUMBER);
00223     $$->values = netlist_append_values ($$->values, $5);
00224   }
00225   | RLC_Device Node Node Value MODEL_Ident PairList Eol {
00226     /* R, L and C definitions specified by a Model */
00227     $$ = spice_create_device ($1);
00228     spice_append_str_value ($$, $2, HINT_NODE);
00229     spice_append_str_value ($$, $3, HINT_NODE);
00230     spice_append_val_value ($$, $4, HINT_NUMBER);
00231     spice_append_str_value ($$, $5, HINT_NAME);
00232     $$->values = netlist_append_values ($$->values, $6);
00233   }
00234   | RLC_Device Node Node MODEL_Ident Value Eol {
00235     /* R, L and C definitions specified by a Model, a variant */
00236     $$ = spice_create_device ($1);
00237     spice_append_str_value ($$, $2, HINT_NODE);
00238     spice_append_str_value ($$, $3, HINT_NODE);
00239     spice_append_val_value ($$, $5, HINT_NUMBER);
00240     spice_append_str_value ($$, $4, HINT_NAME);
00241   }
00242   | RLC_Device Node Node MODEL_Ident PairList Eol {
00243     /* R definitions specified by a Model, yet another variant */
00244     $$ = spice_create_device ($1);
00245     spice_append_str_value ($$, $2, HINT_NODE);
00246     spice_append_str_value ($$, $3, HINT_NODE);
00247     spice_append_str_value ($$, $4, HINT_NAME);
00248     $$->values = netlist_append_values ($$->values, $5);
00249   }
00250   | RLC_Device Node Node Value TC_Value_1 Eol {
00251     /* R definitions including TC1 */
00252     $$ = spice_create_device ($1);
00253     spice_append_str_value ($$, $2, HINT_NODE);
00254     spice_append_str_value ($$, $3, HINT_NODE);
00255     spice_append_val_value ($$, $4, HINT_NUMBER);
00256     $$->values = netlist_append_values ($$->values, $5);
00257   }
00258   | RLC_Device Node Node Value TC_Value_2 Eol {
00259     /* R definitions including TC1/TC2 */
00260     $$ = spice_create_device ($1);
00261     spice_append_str_value ($$, $2, HINT_NODE);
00262     spice_append_str_value ($$, $3, HINT_NODE);
00263     spice_append_val_value ($$, $4, HINT_NUMBER);
00264     $$->values = netlist_append_values ($$->values, $5);
00265   }
00266   | RLC_Device Node Node Value Behave NodeValueList Eol {
00267     /* non-linear C and L poly definitions */
00268     $$ = spice_create_device ($1);
00269     spice_append_str_value ($$, $2, HINT_NODE);
00270     spice_append_str_value ($$, $3, HINT_NODE);
00271     spice_append_val_value ($$, $4, HINT_NUMBER);
00272     spice_append_str_value ($$, $5, HINT_NAME);
00273     $$->values = netlist_append_values ($$->values, $6);
00274   }
00275   | K_Device L_Device L_Device Value Eol {
00276     /* Mutual inductors */
00277     $$ = spice_create_device ($1);
00278     spice_append_str_value ($$, $2, HINT_NAME);
00279     spice_append_str_value ($$, $3, HINT_NAME);
00280     spice_append_val_value ($$, $4, HINT_NUMBER);
00281   }
00282   | IV_Source Node Node ExprList Eol {
00283     /* independent current/voltage sources */
00284     $$ = spice_create_device ($1);
00285     spice_append_str_value ($$, $2, HINT_NODE);
00286     spice_append_str_value ($$, $3, HINT_NODE);
00287     $$->values = netlist_append_values ($$->values, $4);
00288   }
00289   | IV_Source Node Node Value ExprList Eol {
00290     /* independent current/voltage sources given the value */
00291     $$ = spice_create_device ($1);
00292     spice_append_str_value ($$, $2, HINT_NODE);
00293     spice_append_str_value ($$, $3, HINT_NODE);
00294     spice_append_val_value ($$, $4, HINT_NUMBER);
00295     $$->values = netlist_append_values ($$->values, $5);
00296   }
00297   | GE_Source Node Node Behave Digits NodeValueList Eol {
00298     /* voltage controlled source POLY */
00299     if (!strcasecmp ($4, "POLY")) {
00300       $$ = spice_create_device ($1);
00301       spice_append_str_value ($$, $2, HINT_NODE);
00302       spice_append_str_value ($$, $3, HINT_NODE);
00303       spice_append_str_value ($$, $4, HINT_NAME);
00304       spice_append_val_value ($$, $5, HINT_NUMBER);
00305       $$->values = netlist_append_values ($$->values, $6);
00306     }
00307     else {
00308       fprintf (stderr, "spice notice, behavioural %s source ignored\n", $1);
00309       $$ = NULL;
00310     }
00311   }
00312   | GE_Source Node Node Behave Eol {
00313     /* voltage controlled sources OTHER behavioural */
00314     fprintf (stderr, "spice notice, behavioural %s source ignored\n", $1);
00315     $$ = NULL;
00316   }
00317   | GE_Source Node Node Node Node Value Eol {
00318     /* voltage controlled sources */
00319     $$ = spice_create_device ($1);
00320     spice_append_str_value ($$, $2, HINT_NODE);
00321     spice_append_str_value ($$, $3, HINT_NODE);
00322     spice_append_str_value ($$, $4, HINT_NODE);
00323     spice_append_str_value ($$, $5, HINT_NODE);
00324     spice_append_val_value ($$, $6, HINT_NUMBER);
00325   }
00326   | FH_Source FH_Node FH_Node Behave Digits VSourceList NodeValueList Eol {
00327     /* current controlled source POLY */
00328     if (!strcasecmp ($4, "POLY")) {
00329       $$ = spice_create_device ($1);
00330       spice_append_str_value ($$, $2, HINT_NODE);
00331       spice_append_str_value ($$, $3, HINT_NODE);
00332       spice_append_str_value ($$, $4, HINT_NAME);
00333       spice_append_val_value ($$, $5, HINT_NUMBER);
00334       $$->values = netlist_append_values ($$->values, $6);
00335       $$->values = netlist_append_values ($$->values, $7);
00336     }
00337     else {
00338       fprintf (stderr, "spice notice, behavioural %s source ignored\n", $1);
00339       $$ = NULL;
00340     }
00341   }
00342   | FH_Source FH_Node FH_Node Behave Eol {
00343     /* current controlled sources OTHER behavioural */
00344     fprintf (stderr, "spice notice, behavioural %s source ignored\n", $1);
00345     $$ = NULL;
00346   }
00347   | FH_Source FH_Node FH_Node V_Source Value Eol {
00348     /* current controlled sources */
00349     $$ = spice_create_device ($1);
00350     spice_append_str_value ($$, $2, HINT_NODE);
00351     spice_append_str_value ($$, $3, HINT_NODE);
00352     spice_append_str_value ($$, $4, HINT_NAME);
00353     spice_append_val_value ($$, $5, HINT_NUMBER);
00354   }
00355   | MODEL_Action MODEL_Ident MODEL_Spec MODEL_List Eol {
00356     /* device specification */
00357     $$ = spice_create_action ($1, $2);
00358     spice_append_str_value ($$, $3, HINT_NAME | HINT_MSTART);
00359     spice_add_last_hint ($4, HINT_MSTOP);
00360     $$->values = netlist_append_values ($$->values, $4);
00361   }
00362   | Diode_Device Node Node MODEL_Ident DEVICE_List_1 {
00363     /* diode */
00364     $$ = spice_create_device ($1);
00365     spice_append_str_value ($$, $2, HINT_NODE);
00366     spice_append_str_value ($$, $3, HINT_NODE);
00367     spice_append_str_value ($$, $4, HINT_NAME);
00368     $$->values = netlist_append_values ($$->values, $5);
00369   }
00370   | JFET_Device Node Node Node MODEL_Ident DEVICE_List_2 {
00371     /* JFET */
00372     $$ = spice_create_device ($1);
00373     spice_append_str_value ($$, $2, HINT_NODE);
00374     spice_append_str_value ($$, $3, HINT_NODE);
00375     spice_append_str_value ($$, $4, HINT_NODE);
00376     spice_append_str_value ($$, $5, HINT_NAME);
00377     $$->values = netlist_append_values ($$->values, $6);
00378   }
00379   | Bipolar_Device Node Node Node MODEL_Ident DEVICE_List_2 {
00380     /* 3 node BJT */
00381     $$ = spice_create_device ($1);
00382     spice_append_str_value ($$, $2, HINT_NODE);
00383     spice_append_str_value ($$, $3, HINT_NODE);
00384     spice_append_str_value ($$, $4, HINT_NODE);
00385     spice_append_str_value ($$, $5, HINT_NAME);
00386     $$->values = netlist_append_values ($$->values, $6);
00387   }
00388   | Bipolar_Device Node Node Node Node MODEL_Ident DEVICE_List_2 {
00389     /* 4 node BJT */
00390     $$ = spice_create_device ($1);
00391     spice_append_str_value ($$, $2, HINT_NODE);
00392     spice_append_str_value ($$, $3, HINT_NODE);
00393     spice_append_str_value ($$, $4, HINT_NODE);
00394     spice_append_str_value ($$, $5, HINT_NODE);
00395     spice_append_str_value ($$, $6, HINT_NAME);
00396     $$->values = netlist_append_values ($$->values, $7);
00397   }
00398   | MOSFET_Device Node Node Node Node MODEL_Ident DEVICE_List_3 {
00399     /* MOS */
00400     $$ = spice_create_device ($1);
00401     spice_append_str_value ($$, $2, HINT_NODE);
00402     spice_append_str_value ($$, $3, HINT_NODE);
00403     spice_append_str_value ($$, $4, HINT_NODE);
00404     spice_append_str_value ($$, $5, HINT_NODE);
00405     spice_append_str_value ($$, $6, HINT_NAME);
00406     $$->values = netlist_append_values ($$->values, $7);
00407   }
00408   | MESFET_Device Node Node Node MODEL_Ident DEVICE_List_2 {
00409     /* MES */
00410     $$ = spice_create_device ($1);
00411     spice_append_str_value ($$, $2, HINT_NODE);
00412     spice_append_str_value ($$, $3, HINT_NODE);
00413     spice_append_str_value ($$, $4, HINT_NODE);
00414     spice_append_str_value ($$, $5, HINT_NAME);
00415     $$->values = netlist_append_values ($$->values, $6);
00416   }
00417   | TRAN_Action ValueList Eol {
00418     /* transient analysis */
00419     $$ = spice_create_action ($1, strdup ($1));
00420     $$->values = $2;
00421   }
00422   | PLOT_Action SIM_Type PLOT_List Eol {
00423     /* plotting */
00424     $$ = spice_create_action ($1, strdup ($1));
00425     spice_append_str_value ($$, $2, HINT_NAME);
00426     $$->values = netlist_append_values ($$->values, $3);
00427   }
00428   | AC_Action Expr Eol {
00429     /* AC analysis */
00430     $$ = spice_create_action ($1, strdup ($1));
00431     $$->values = $2;
00432   }
00433   | DC_Action Eol {
00434     /* single DC analysis */
00435     $$ = spice_create_action ($1, strdup ($1));
00436   }
00437   | DC_Action DC_List Eol {
00438     /* DC analysis first order */
00439     $$ = spice_create_action ($1, strdup ($1));
00440     $$->values = $2;
00441   }
00442   | DC_Action DC_List DC_List Eol {
00443     /* DC analysis second order */
00444     $$ = spice_create_action ($1, strdup ($1));
00445     $$->values = netlist_append_values ($2, $3);
00446   }
00447   | PRINT_Action SIM_Type PRINT_List Eol {
00448     /* printing specifying the analysis type */
00449     $$ = spice_create_action ($1, strdup ($1));
00450     spice_append_str_value ($$, $2, HINT_NAME);
00451     $$->values = netlist_append_values ($$->values, $3);
00452   }
00453   | PRINT_Action PRINT_List Eol {
00454     /* printing */
00455     $$ = spice_create_action ($1, strdup ($1));
00456     $$->values = $2;
00457   }
00458   | PRINT_Action SIM_Type ALL_Special Eol {
00459     /* printing */
00460     $$ = spice_create_action ($1, strdup ($1));
00461     spice_append_str_value ($$, $2, HINT_NAME);
00462     spice_append_str_value ($$, $3, HINT_NAME);
00463   }
00464   | OPTIONS_Action OPTIONS_List Eol {
00465     /* general analysis options */
00466     $$ = spice_create_action ($1, strdup ($1));
00467     $$->values = $2;
00468   }
00469   | TEMP_Action ValueList Eol {
00470     /* temperatur analysis (Spice 2g6) */
00471     $$ = spice_create_action ($1, strdup ($1));
00472     $$->values = $2;
00473   }
00474   | WIDTH_Action PairList Eol {
00475     /* TODO: default width of ??? */
00476     $$ = spice_create_action ($1, strdup ($1));
00477     $$->values = $2;
00478   }
00479   | NOISE_Action VOLTAGE_Output IV_Reference Expr Eol {
00480     /* noise analysis */
00481     $$ = spice_create_action ($1, strdup ($1));
00482     $$->values = netlist_append_values ($$->values, $2);
00483     spice_append_str_value ($$, $3, HINT_NAME);
00484     $$->values = netlist_append_values ($$->values, $4);
00485   }
00486   | PZ_Action Node Node Node Node CurVol PoleZero Eol {
00487     /* pole-zero analysis */
00488     $$ = spice_create_action ($1, strdup ($1));
00489     spice_append_str_value ($$, $2, HINT_NODE);
00490     spice_append_str_value ($$, $3, HINT_NODE);
00491     spice_append_str_value ($$, $4, HINT_NODE);
00492     spice_append_str_value ($$, $5, HINT_NODE);
00493     spice_append_str_value ($$, $6, HINT_NAME);
00494     spice_append_str_value ($$, $7, HINT_NAME);
00495   }
00496   | X_Device NodeList Eol {
00497     /* subcircuit call */
00498     $$ = spice_create_device ($1);
00499     spice_set_last_hint ($2, HINT_NAME);
00500     $$->values = $2;
00501   }
00502   | S_Device Node Node Node Node MODEL_Ident SWITCH_State Eol {
00503     /* voltage controlled switch */
00504     $$ = spice_create_device ($1);
00505     spice_append_str_value ($$, $2, HINT_NODE);
00506     spice_append_str_value ($$, $3, HINT_NODE);
00507     spice_append_str_value ($$, $4, HINT_NODE);
00508     spice_append_str_value ($$, $5, HINT_NODE);
00509     spice_append_str_value ($$, $6, HINT_NAME);
00510     $$->values = netlist_append_values ($$->values, $7);
00511   }
00512   | W_Device Node Node V_Source MODEL_Ident SWITCH_State Eol {
00513     /* current controlled switch */
00514     $$ = spice_create_device ($1);
00515     spice_append_str_value ($$, $2, HINT_NODE);
00516     spice_append_str_value ($$, $3, HINT_NODE);
00517     spice_append_str_value ($$, $4, HINT_NAME);
00518     spice_append_str_value ($$, $5, HINT_NAME);
00519     $$->values = netlist_append_values ($$->values, $6);
00520   }
00521   | O_Device Node Node Node Node MODEL_Ident Eol {
00522     /* lossy transline */
00523     $$ = spice_create_device ($1);
00524     spice_append_str_value ($$, $2, HINT_NODE);
00525     spice_append_str_value ($$, $3, HINT_NODE);
00526     spice_append_str_value ($$, $4, HINT_NODE);
00527     spice_append_str_value ($$, $5, HINT_NODE);
00528     spice_append_str_value ($$, $6, HINT_NAME);
00529   }
00530   | U_Device Node Node Node MODEL_Ident PairList Eol {
00531     /* distributed lossy transline */
00532     $$ = spice_create_device ($1);
00533     spice_append_str_value ($$, $2, HINT_NODE);
00534     spice_append_str_value ($$, $3, HINT_NODE);
00535     spice_append_str_value ($$, $4, HINT_NODE);
00536     spice_append_str_value ($$, $5, HINT_NAME);
00537     $$->values = netlist_append_values ($$->values, $6);
00538   }
00539   | T_Device Node Node Node Node PairList Eol {
00540     /* lossless transline */
00541     $$ = spice_create_device ($1);
00542     spice_append_str_value ($$, $2, HINT_NODE);
00543     spice_append_str_value ($$, $3, HINT_NODE);
00544     spice_append_str_value ($$, $4, HINT_NODE);
00545     spice_append_str_value ($$, $5, HINT_NODE);
00546     $$->values = netlist_append_values ($$->values, $6);
00547   }
00548   | T_Device Node Node Node Node PairList IC_Condition_4 Eol {
00549     /* lossless transline and initial condition */
00550     $$ = spice_create_device ($1);
00551     spice_append_str_value ($$, $2, HINT_NODE);
00552     spice_append_str_value ($$, $3, HINT_NODE);
00553     spice_append_str_value ($$, $4, HINT_NODE);
00554     spice_append_str_value ($$, $5, HINT_NODE);
00555     $$->values = netlist_append_values ($$->values, $6);
00556     $$->values = netlist_append_values ($$->values, $7);
00557   }
00558   | OP_Action Eol {
00559     /* operating point analysis */
00560     $$ = spice_create_action ($1, strdup ($1));
00561   }
00562   | SAVE_Action Eol {
00563     /* saving action */
00564     $$ = spice_create_action ($1, strdup ($1));
00565   }
00566   | SENS_Action Eol {
00567     /* sensitivity analysis */
00568     $$ = spice_create_action ($1, strdup ($1));
00569   }
00570   | TF_Action Eol {
00571     /* transfer function analysis */
00572     $$ = spice_create_action ($1, strdup ($1));
00573   }
00574   | FOUR_Action Eol {
00575     /* fourier analysis */
00576     $$ = spice_create_action ($1, strdup ($1));
00577   }
00578   | B_Source Eol {
00579     /* non-linear dependent sources */
00580     $$ = spice_create_device ($1);
00581   }
00582   | DISTO_Action Expr Eol {
00583     /* distortion analysis */
00584     $$ = spice_create_action ($1, strdup ($1));
00585     $$->values = $2;
00586   }
00587   | INCLUDE_Action File Eol {
00588     /* file include */
00589     $$ = spice_create_action ($1, strdup ($1));
00590     struct value_t * file = create_value ();
00591     file->ident = $2;
00592     file->hint = HINT_NAME;
00593     $$->values = file;
00594   }
00595   | NODESET_Action NODESET_List Eol {
00596     /* nodeset functionality */
00597     $$ = spice_create_action ($1, strdup ($1));
00598     $$->values = $2;
00599   }
00600 ;
00601 
00602 TC_Value_1:
00603   TC_Special Value {
00604     $$ = NULL;
00605     $$ = spice_create_par_value ($1, $2);
00606   }
00607 ;
00608 
00609 TC_Value_2:
00610   TC_Special Value Value {
00611     $$ = NULL;
00612     $$ = spice_create_par_value ($1, $2);
00613     $$ = spice_append_val_values ($$, $3, HINT_NUMBER);
00614   }
00615 ;
00616 
00617 IC_Condition_1:
00618   IC_Special Value {
00619     $$ = NULL;
00620     $$ = spice_append_str_values ($$, $1, HINT_NAME);
00621     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00622   }
00623 ;
00624 
00625 IC_Condition_2:
00626   IC_Special Value Value {
00627     $$ = NULL;
00628     $$ = spice_append_str_values ($$, $1, HINT_NAME);
00629     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00630     $$ = spice_append_val_values ($$, $3, HINT_NUMBER);
00631   }
00632 
00633 IC_Condition_3:
00634   IC_Special Value Value Value {
00635     $$ = NULL;
00636     $$ = spice_append_str_values ($$, $1, HINT_NAME);
00637     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00638     $$ = spice_append_val_values ($$, $3, HINT_NUMBER);
00639     $$ = spice_append_val_values ($$, $4, HINT_NUMBER);
00640   }
00641 ;
00642 
00643 IC_Condition_4:
00644   IC_Special Value Value Value Value {
00645     $$ = NULL;
00646     $$ = spice_append_str_values ($$, $1, HINT_NAME);
00647     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00648     $$ = spice_append_val_values ($$, $3, HINT_NUMBER);
00649     $$ = spice_append_val_values ($$, $4, HINT_NUMBER);
00650     $$ = spice_append_val_values ($$, $5, HINT_NUMBER);
00651   }
00652 ;
00653 
00654 Output_Range:
00655   Value Value { /* range specification during plotting */
00656     $$ = NULL;
00657     $$ = spice_append_val_values ($$, $1, HINT_NUMBER);
00658     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00659   }
00660 ;
00661 
00662 VOLTAGE_Output:
00663   Node { // TODO: 2 reduce/reduce, 2 shift/reduce
00664     /* print/plot specification of node voltage */
00665     $$ = NULL;
00666     $$ = spice_append_str_values ($$, strdup ("V"), HINT_NAME | HINT_MSTART);
00667     $$ = spice_append_str_values ($$, $1, HINT_NODE | HINT_MSTOP);
00668   }
00669   | VoltFunc Node { // TODO: 2 reduce/reduce
00670     /* print/plot specification of node voltage */
00671     $$ = NULL;
00672     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTART);
00673     $$ = spice_append_str_values ($$, $2, HINT_NODE | HINT_MSTOP);
00674   }
00675   | VoltFunc Node Node {
00676     /* print/plot specification of differential node voltages */
00677     $$ = NULL;
00678     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTART);
00679     $$ = spice_append_str_values ($$, $2, HINT_NODE);
00680     $$ = spice_append_str_values ($$, $3, HINT_NODE | HINT_MSTOP);    
00681   }
00682 ;
00683 
00684 /* reference to a current or voltage source */
00685 IV_Reference: I_Source | V_Source;
00686 
00687 CURRENT_Output:
00688   CurrFunc V_Source {
00689     /* print/plot specification of branch current */
00690     $$ = NULL;
00691     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTART);
00692     $$ = spice_append_str_values ($$, $2, HINT_NAME | HINT_MSTOP);
00693   }
00694   | BranchFunc {
00695     /* print/plot specification of branch current */
00696     $$ = NULL;
00697     $$ = spice_append_str_values ($$, strdup ("I"), HINT_NAME | HINT_MSTART);
00698     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTOP);
00699   }
00700   | OpFunc {
00701     /* print/plot specification of operating point */
00702     $$ = NULL;
00703     $$ = spice_append_str_values ($$, strdup ("OP"), HINT_NAME | HINT_MSTART);
00704     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTOP);
00705   }
00706 ;
00707 
00708 PLOT_List: /* nothing */ { $$ = NULL; }
00709   | VOLTAGE_Output PLOT_List {
00710     $$ = netlist_append_values ($1, $2);
00711   }
00712   | VOLTAGE_Output Output_Range PLOT_List {
00713     $$ = netlist_append_values ($1, $2);
00714     $$ = netlist_append_values ($$, $3);
00715   }
00716   | CURRENT_Output PLOT_List {
00717     $$ = netlist_append_values ($1, $2);
00718   }
00719   | CURRENT_Output Output_Range PLOT_List {
00720     $$ = netlist_append_values ($1, $2);
00721     $$ = netlist_append_values ($$, $3);
00722   }
00723 ;
00724 
00725 SWITCH_State: /* nothing */ { $$ = NULL; }
00726   | ON_Special {
00727     $$ = spice_create_str_value ($1, HINT_NAME);
00728   }
00729   | OFF_Special {
00730     $$ = spice_create_str_value ($1, HINT_NAME);
00731   }
00732 ;
00733 
00734 PRINT_List: /* nothing */ { $$ = NULL; }
00735   | VOLTAGE_Output PLOT_List {
00736     $$ = netlist_append_values ($1, $2);
00737   }
00738   | CURRENT_Output PLOT_List {
00739     $$ = netlist_append_values ($1, $2);
00740   }
00741 ;
00742 
00743 OPTIONS_List: /* nothing */ { $$ = NULL; }
00744   | Options OPTIONS_List {
00745     $$ = spice_create_str_value ($1, HINT_NAME);
00746     $$ = netlist_append_values ($$, $2);
00747   }
00748   | Identifier Value OPTIONS_List {
00749     $$ = spice_create_par_value ($1, $2);
00750     $$ = netlist_append_values ($$, $3);
00751   }
00752 ;
00753 
00754 MODEL_List: /* nothing */ { $$ = NULL; }
00755   | ModelProps MODEL_List {
00756     $$ = spice_create_str_value ($1, HINT_NAME);
00757     $$ = netlist_append_values ($$, $2);
00758   }
00759   | Identifier Value MODEL_List {
00760     $$ = spice_create_par_value ($1, $2);
00761     $$ = netlist_append_values ($$, $3);
00762   }
00763 ;
00764 
00765 NODESET_List: /* nothing */ { $$ = NULL; }
00766   | VoltFunc Node Value NODESET_List {
00767     $$ = NULL;
00768     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTART);
00769     $$ = spice_append_str_values ($$, $2, HINT_NODE | HINT_MSTOP);
00770     $$ = spice_append_str_values ($$, $3, HINT_NUMBER);
00771     $$ = netlist_append_values ($$, $4);
00772   }
00773 ;
00774 
00775 DEVICE_List_1: /* nothing */ { $$ = NULL; }
00776   | TEMP_Special Value DEVICE_List_1 {
00777     $$ = spice_create_par_value ($1, $2);
00778     $$ = netlist_append_values ($$, $3);
00779   }
00780   | Value DEVICE_List_1 {
00781     $$ = spice_create_par_value (strdup ("Area"), $1);
00782     $$ = netlist_append_values ($$, $2);
00783   }
00784   | OFF_Special DEVICE_List_1 {
00785     $$ = spice_create_val_value ($1, HINT_NAME);
00786     $$ = netlist_append_values ($$, $2);
00787   }
00788   | IC_Condition_1 DEVICE_List_1 {
00789     $$ = netlist_append_values ($1, $2);
00790   }
00791 ;
00792 
00793 DEVICE_List_2: /* nothing */ { $$ = NULL; }
00794   | TEMP_Special Value DEVICE_List_2 {
00795     $$ = spice_create_par_value ($1, $2);
00796     $$ = netlist_append_values ($$, $3);
00797   }
00798   | Value DEVICE_List_2 {
00799     $$ = spice_create_par_value (strdup ("Area"), $1);
00800     $$ = netlist_append_values ($$, $2);
00801   }
00802   | OFF_Special DEVICE_List_2 {
00803     $$ = spice_create_val_value ($1, HINT_NAME);
00804     $$ = netlist_append_values ($$, $2);
00805   }
00806   | IC_Condition_2 DEVICE_List_2 {
00807     $$ = netlist_append_values ($1, $2);
00808   }
00809   | MOS_Special Value DEVICE_List_2 {
00810     $$ = spice_create_par_value ($1, $2);
00811     $$ = netlist_append_values ($$, $3);
00812   }
00813 ;
00814 
00815 DEVICE_List_3: /* nothing */ { $$ = NULL; }
00816   | TEMP_Special Value DEVICE_List_3 {
00817     $$ = spice_create_par_value ($1, $2);
00818     $$ = netlist_append_values ($$, $3);
00819   }
00820   | MOS_Special Value DEVICE_List_3 {
00821     $$ = spice_create_par_value ($1, $2);
00822     $$ = netlist_append_values ($$, $3);
00823   }
00824   | Value DEVICE_List_3 {
00825     $$ = spice_create_val_value ($1, HINT_NUMBER);
00826     $$ = netlist_append_values ($$, $2);
00827   }
00828   | OFF_Special DEVICE_List_3 {
00829     $$ = spice_create_val_value ($1, HINT_NAME);
00830     $$ = netlist_append_values ($$, $2);
00831   }
00832   | IC_Condition_3 DEVICE_List_3 {
00833     $$ = netlist_append_values ($1, $2);
00834   }
00835 ;
00836 
00837 MODEL_Ident: Identifier | MODEL_Spec;
00838 
00839 DC_List:
00840   IV_Reference Value Value Value {
00841     /* identification of a DC sweep */
00842     $$ = NULL;
00843     $$ = spice_append_str_values ($$, $1, HINT_NAME | HINT_MSTART);
00844     $$ = spice_append_val_values ($$, $2, HINT_NUMBER);
00845     $$ = spice_append_val_values ($$, $3, HINT_NUMBER);
00846     $$ = spice_append_val_values ($$, $4, HINT_NUMBER | HINT_MSTOP);
00847   }
00848 ;
00849 
00850 Value: Digits | Floats;
00851 
00852 Node: Digits | Nodes | Identifier;
00853 
00854 FH_Node: Node | V_Source;
00855 
00856 PairList: /* nothing */ { $$ = NULL; }
00857   | Identifier Value PairList {
00858     $$ = spice_create_par_value ($1, $2);
00859     $$->next = $3;
00860   }
00861 ;
00862 
00863 ValueList: /* nothing */ { $$ = NULL; }
00864   | Value ValueList {
00865     $$ = spice_create_val_value ($1, HINT_NUMBER);
00866     $$->next = $2;
00867   }
00868 ;
00869 
00870 NodeValueList: /* nothing */ { $$ = NULL; }
00871   | Node NodeValueList {
00872     $$ = spice_create_str_value ($1, HINT_NODE);
00873     $$->next = $2;
00874   }
00875   | Floats NodeValueList {
00876     $$ = spice_create_val_value ($1, HINT_NUMBER);
00877     $$->next = $2;
00878   }
00879 ;
00880 
00881 NodeList: /* nothing */ { $$ = NULL; }
00882   | Node NodeList {
00883     $$ = spice_create_str_value ($1, HINT_NODE);
00884     $$->next = $2;
00885   }
00886 ;
00887 
00888 VSourceList: /* nothing */ { $$ = NULL; }
00889   | V_Source VSourceList {
00890     $$ = spice_create_str_value ($1, HINT_NAME);
00891     $$->next = $2;
00892   }
00893 ;
00894 
00895 Expr:
00896   Function ValueList {
00897     $$ = spice_create_str_value ($1, HINT_NAME | HINT_MSTART);
00898     spice_add_last_hint ($2, HINT_MSTOP);
00899     $$->next = $2;
00900   }
00901 ;
00902 
00903 ExprList: /* nothing */ { $$ = NULL; }
00904   | Expr ExprList {
00905     $$ = netlist_append_values ($1, $2);
00906   }
00907 ;
00908 
00909 Subcircuit:
00910   BeginSub SubBody EndSub {
00911     $1->sub = $2;
00912     $$ = $1;
00913     $2 = NULL;
00914   }
00915 ;
00916 
00917 BeginSub:
00918   SUBCKT_Action SubCkt_Ident NodeList Eol {
00919     $$ = spice_create_action ($1, $2);
00920     $$->values = $3;
00921   }
00922 ;
00923 
00924 SubBody: /* nothing */ { $$ = NULL; }
00925   | SubBodyLine SubBody { /* chain definitions here */
00926     if ($1) {
00927       $1->next = $2;
00928       $$ = $1;
00929     }
00930     else {
00931       $$ = $2;
00932     }
00933   }
00934 ;
00935 
00936 SubCkt_Ident: Identifier;
00937 
00938 EndSub:
00939     ENDS_Action { /* nothing to do */ }
00940   | ENDS_Action SubCkt_Ident { free ($2); /* nothing to do */ }
00941 ;
00942 
00943 SubBodyLine:
00944   DefinitionLine { /* chain definitions here */
00945     if ($1) {
00946       $1->next = $$;
00947       $$ = $1;
00948     }
00949   }
00950   | Subcircuit { /* do nothing here, see subcircuit rule */ }
00951   | Eol {
00952     $$ = NULL;
00953   }
00954 ;
00955 
00956 %%
00957 
00958 int spice_error (const char * error) {
00959   fprintf (stderr, "line %d: %s\n", spice_lineno, error);
00960   return 0;
00961 }