Qucs-core  0.0.19
parse_netlist.y
Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 
00003 %{
00004 /*
00005  * parse_netlist.y - parser for the Qucs netlist
00006  *
00007  * Copyright (C) 2003, 2004, 2005, 2006, 2007 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 
00036 #define YYERROR_VERBOSE 42
00037 #define YYDEBUG 1
00038 #define YYMAXDEPTH 1000000
00039 
00040 #include "check_netlist.h"
00041 #include "logging.h"
00042 #include "equation.h"
00043 #include "range.h"
00044 
00045 using namespace qucs;
00046 
00047 %}
00048 
00049 %name-prefix "netlist_"
00050 
00051 %token InvalidCharacter
00052 %token Identifier
00053 %token Assign
00054 %token ScaleOrUnit
00055 %token Eol
00056 %token Eqn
00057 %token DefSub
00058 %token EndSub
00059 %token REAL
00060 %token IMAG
00061 %token COMPLEX
00062 %token Character
00063 %token STRING
00064 
00065 %right '='
00066 %right '?' ':'
00067 %left  Or
00068 %left  And
00069 %left  NotEqual Equal
00070 %left  Less Greater LessOrEqual GreaterOrEqual
00071 %left  '-' '+'
00072 %left  '*' '/' '%'
00073 %right Not
00074 %left  NEG     /* unary negation */
00075 %left  POS     /* unary non-negation */
00076 %right '^'
00077 
00078 %union {
00079   char * ident;
00080   char * str;
00081   double d;
00082   char chr;
00083   struct definition_t * definition;
00084   struct definition_t * subcircuit;
00085   struct node_t * node;
00086   struct pair_t * pair;
00087   struct value_t * value;
00088   struct {
00089     double r;
00090     double i;
00091   } c;
00092   qucs::eqn::node * eqn;
00093   qucs::eqn::constant * con;
00094   qucs::eqn::reference * ref;
00095   qucs::eqn::application * app;
00096   qucs::eqn::assignment * assign;
00097 }
00098 
00099 %type <ident> Identifier Assign NodeIdentifier InstanceIdentifier
00100 %type <str> ScaleOrUnit
00101 %type <d> REAL IMAG
00102 %type <c> COMPLEX
00103 %type <chr> Character
00104 %type <str> STRING
00105 %type <definition> DefinitionLine ActionLine DefBody DefBodyLine EquationLine
00106 %type <definition> InputList InputLine
00107 %type <subcircuit> DefBegin SubcircuitBody
00108 %type <node> NodeList
00109 %type <pair> PairList
00110 %type <value> PropertyValue ValueList Value PropertyReal
00111 %type <eqn> EquationList Expression ExpressionList
00112 %type <assign> Equation
00113 %type <con> Constant
00114 %type <ref> Reference
00115 %type <app> Application Range Matrix Vector
00116 %type <eqn> ExpressionMatrix ExpressionVector
00117 %type <eqn> ExpressionRowList ExpressionCol ExpressionColList
00118 
00119 %%
00120 
00121 Input:
00122   InputList {
00123     definition_root = $1;
00124   }
00125 ;
00126 
00127 InputList: /* nothing */ { $$ = NULL; }
00128   | InputLine InputList {
00129     if ($1) {
00130       $1->next = $2;
00131       $$ = $1;
00132     } else {
00133       $$ = $2;
00134     }
00135   }
00136 ;
00137 
00138 InputLine:
00139   SubcircuitBody {
00140     $$ = $1;
00141   }
00142   | EquationLine
00143   | ActionLine
00144   | DefinitionLine
00145   | Eol {
00146     $$ = NULL;
00147   }
00148 ;
00149 
00150 /* An action line in the netlist, i.e. the specification of the type
00151    of simulation to be performed  */
00152 ActionLine:
00153   '.' Identifier ':' InstanceIdentifier PairList Eol {
00154     $$ = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
00155     $$->action = PROP_ACTION;
00156     $$->type = $2;
00157     $$->instance = $4;
00158     $$->pairs = $5;
00159     $$->line = netlist_lineno;
00160   }
00161 ;
00162 
00163 /* A definition line in the netlist, i.e. a component specification
00164    such as R:R1 _net0 gnd R="50 Ohm" Temp="26.85" Tc1="0.0" Tc2="0.0" Tnom="26.85"
00165  */
00166 DefinitionLine:
00167   Identifier ':' InstanceIdentifier NodeList PairList Eol {
00168     $$ = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
00169     $$->action = PROP_COMPONENT;
00170     $$->type = $1;
00171     $$->instance = $3;
00172     $$->nodes = $4;
00173     $$->pairs = $5;
00174     $$->line = netlist_lineno;
00175   }
00176 ;
00177 
00178 InstanceIdentifier:
00179     Identifier  { $$ = $1; }
00180   | ScaleOrUnit { $$ = $1; }
00181 ;
00182 
00183 NodeIdentifier:
00184     Identifier  { $$ = $1; }
00185   | ScaleOrUnit { $$ = $1; }
00186 ;
00187 
00188 /* List of nodes for a component */
00189 NodeList: /* nothing */ { $$ = NULL; }
00190   | NodeIdentifier NodeList {
00191     $$ = (struct node_t *) calloc (sizeof (struct node_t), 1);
00192     $$->node = $1;
00193     $$->next = $2;
00194   }
00195 ;
00196 
00197 /* Assigns the list of key-value pairs x="y" */
00198 PairList: /* nothing */ { $$ = NULL; }
00199   | Assign Value PairList {
00200     $$ = (struct pair_t *) calloc (sizeof (struct pair_t), 1);
00201     $$->key = $1;
00202     $$->value = $2;
00203     $$->next = $3;
00204   }
00205   | Assign NoneValue PairList {
00206     if (0) {
00207       $$ = (struct pair_t *) calloc (sizeof (struct pair_t), 1);
00208       $$->key = $1;
00209       $$->value = NULL;
00210       $$->next = $3;
00211     } else {
00212       free ($1);
00213       $$ = $3;
00214     }
00215   }
00216 ;
00217 
00218 /* A empty value in a pair list */
00219 NoneValue:  { /* nothing */ }
00220   | '"' '"' { /* also nothing */ }
00221 ;
00222 
00223 /* A property value, can either be on its own or enclosed in quotes */
00224 Value:
00225   PropertyValue {
00226     $$ = $1;
00227   }
00228   | '"' PropertyValue '"' {
00229     $$ = $2;
00230   }
00231 ;
00232 
00233 PropertyReal:
00234   REAL {
00235     $$ = create_value ();
00236     $$->value = $1;
00237   }
00238   | REAL ScaleOrUnit {
00239     $$ = create_value ();
00240     $$->value = $1;
00241     $$->scale = $2;
00242   }
00243   | REAL ScaleOrUnit ScaleOrUnit {
00244     $$ = create_value ();
00245     $$->value = $1;
00246     $$->scale = $2;
00247     $$->unit = $3;
00248   }
00249 ;
00250 
00251 PropertyValue:
00252   PropertyReal {
00253     $$ = $1;
00254   }
00255   | InstanceIdentifier {
00256     $$ = create_value ();
00257     $$->ident = $1;
00258   }
00259   | '[' InstanceIdentifier ']' {
00260     $$ = create_value ();
00261     $$->ident = $2;
00262   }
00263   | '[' ValueList ']' {
00264     $$ = $2;
00265   }
00266 ;
00267 
00268 ValueList: /* nothing */ { $$ = NULL; }
00269   | PropertyReal {
00270     $1->next = NULL;
00271     $$ = $1;
00272   }
00273   | PropertyReal ';' ValueList {
00274     $1->next = $3;
00275     $$ = $1;
00276   }
00277 ;
00278 
00279 EquationLine:
00280   Eqn ':' InstanceIdentifier Equation EquationList Eol {
00281     /* create equation definition */
00282     $$ = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
00283     $$->type = strdup ("Eqn");
00284     $$->instance = $3;
00285     $$->action = PROP_ACTION;
00286     $$->line = netlist_lineno;
00287     $4->setInstance ($3);
00288     $4->setNext ($5);
00289     $4->applyInstance ();
00290     $$->eqns = $4;
00291   }
00292 ;
00293 
00294 EquationList: /* nothing */ { $$ = NULL; }
00295   | Equation EquationList {
00296     $1->setNext ($2);
00297     $$ = $1;
00298   }
00299 ;
00300 
00301 Equation:
00302   Assign '"' Expression '"' {
00303     $$ = new eqn::assignment ();
00304     $$->result = $1;
00305     $$->body = $3;
00306   }
00307 ;
00308 
00309 Expression:
00310     Constant {
00311     $$ = $1;
00312   }
00313   | Reference {
00314     $$ = $1;
00315   }
00316   | Application {
00317     $$ = $1;
00318   }
00319   | '(' Expression ')' {
00320     $$ = $2;
00321   }
00322   | '[' Vector ']' {
00323     $$ = $2;
00324   }
00325   | '[' Matrix ']' {
00326     $$ = $2;
00327   }
00328 ;
00329 
00330 ExpressionCol:
00331   Expression ExpressionColList {
00332     $1->appendNodes ($2);
00333     $$ = $1;
00334   }
00335 ;
00336 
00337 ExpressionColList:  /* nothing */ { $$ = NULL; }
00338   | ',' Expression ExpressionColList {
00339     $2->appendNodes ($3);
00340     $$ = $2;
00341   }
00342 ;
00343 
00344 ExpressionVector:
00345   ExpressionCol
00346 ;
00347 
00348 Vector:
00349   ExpressionVector {
00350     $$ = new eqn::application ();
00351     $$->n = strdup ("vector");
00352     $$->nargs = $1->count ();
00353     $$->args = $1;
00354   }
00355 ;
00356 
00357 ExpressionRowList:  /* nothing */ { $$ = NULL; }
00358   | ';' ExpressionCol ExpressionRowList {
00359     eqn::constant * c = new eqn::constant (eqn::TAG_CHAR);
00360     c->chr = ';';
00361     c->appendNodes ($2);
00362     $2->appendNodes ($3);
00363     $$ = c;
00364   }
00365 ;
00366 
00367 ExpressionMatrix:
00368   ExpressionCol ';' ExpressionCol ExpressionRowList {
00369     eqn::constant * c = new eqn::constant (eqn::TAG_CHAR);
00370     c->chr = ';';
00371     c->appendNodes ($3);
00372     $3->appendNodes ($4);
00373     $1->appendNodes (c);
00374     $$ = $1;
00375   }
00376 ;
00377 
00378 Matrix:
00379   ExpressionMatrix {
00380     $$ = new eqn::application ();
00381     $$->n = strdup ("matrix");
00382     $$->nargs = $1->count ();
00383     $$->args = $1;
00384   }
00385 ;
00386 
00387 Constant:
00388     REAL {
00389     $$ = new eqn::constant (eqn::TAG_DOUBLE);
00390     $$->d = $1;
00391   }
00392   | IMAG {
00393     $$ = new eqn::constant (eqn::TAG_COMPLEX);
00394     $$->c = new nr_complex_t (0.0, $1);
00395   }
00396   | Character {
00397     $$ = new eqn::constant (eqn::TAG_CHAR);
00398     $$->chr = $1;
00399   }
00400   | STRING {
00401     $$ = new eqn::constant (eqn::TAG_STRING);
00402     $$->s = $1;
00403   }
00404 ;
00405 
00406 Range:
00407   Expression ':' Expression {
00408     $$ = new eqn::application ();
00409     $$->n = strdup ("range");
00410     $$->nargs = 2;
00411     $1->append ($3);
00412     $$->args = $1;
00413   }
00414   | ':' Expression {
00415     $$ = new eqn::application ();
00416     $$->n = strdup ("range");
00417     $$->nargs = 2;
00418     eqn::constant * c = new eqn::constant (eqn::TAG_CHAR);
00419     c->chr = '?';
00420     c->append ($2);
00421     $$->args = c;
00422   }
00423   | Expression ':' {
00424     $$ = new eqn::application ();
00425     $$->n = strdup ("range");
00426     $$->nargs = 2;
00427     eqn::constant * c = new eqn::constant (eqn::TAG_CHAR);
00428     c->chr = '?';
00429     $1->append (c);
00430     $$->args = $1;
00431   }
00432   | ':' {
00433     $$ = new eqn::application ();
00434     $$->n = strdup ("range");
00435     $$->nargs = 2;
00436     eqn::constant * c1 = new eqn::constant (eqn::TAG_CHAR);
00437     eqn::constant * c2 = new eqn::constant (eqn::TAG_CHAR);
00438     c1->chr = '?';
00439     c2->chr = '?';
00440     c1->append (c2);
00441     $$->args = c1;
00442   }
00443 ;
00444 
00445 Reference:
00446   Identifier {
00447     $$ = new eqn::reference ();
00448     $$->n = $1;
00449   }
00450 ;
00451 
00452 Application:
00453     Identifier '(' ExpressionList ')' {
00454     $$ = new eqn::application ();
00455     $$->n = $1;
00456     $$->nargs = $3->count ();
00457     $$->args = $3;
00458   }
00459   | Reference '[' ExpressionList ']' {
00460     $$ = new eqn::application ();
00461     $$->n = strdup ("array");
00462     $$->nargs = 1 + $3->count ();
00463     $1->setNext ($3);
00464     $$->args = $1;
00465   }
00466   | Expression '+' Expression {
00467     $$ = new eqn::application ();
00468     $$->n = strdup ("+");
00469     $$->nargs = 2;
00470     $1->append ($3);
00471     $$->args = $1;
00472   }
00473   | Expression '-' Expression {
00474     $$ = new eqn::application ();
00475     $$->n = strdup ("-");
00476     $$->nargs = 2;
00477     $1->append ($3);
00478     $$->args = $1;
00479   }
00480   | Expression '*' Expression {
00481     $$ = new eqn::application ();
00482     $$->n = strdup ("*");
00483     $$->nargs = 2;
00484     $1->append ($3);
00485     $$->args = $1;
00486   }
00487   | Expression '/' Expression {
00488     $$ = new eqn::application ();
00489     $$->n = strdup ("/");
00490     $$->nargs = 2;
00491     $1->append ($3);
00492     $$->args = $1;
00493   }
00494   | Expression '%' Expression {
00495     $$ = new eqn::application ();
00496     $$->n = strdup ("%");
00497     $$->nargs = 2;
00498     $1->append ($3);
00499     $$->args = $1;
00500   }
00501   | '+' Expression %prec POS {
00502     $$ = new eqn::application ();
00503     $$->n = strdup ("+");
00504     $$->nargs = 1;
00505     $$->args = $2;
00506   }
00507   | '-' Expression %prec NEG {
00508     $$ = new eqn::application ();
00509     $$->n = strdup ("-");
00510     $$->nargs = 1;
00511     $$->args = $2;
00512   }
00513   | Expression '^' Expression {
00514     $$ = new eqn::application ();
00515     $$->n = strdup ("^");
00516     $$->nargs = 2;
00517     $1->append ($3);
00518     $$->args = $1;
00519   }
00520   | Expression '?' Expression ':' Expression {
00521     $$ = new eqn::application ();
00522     $$->n = strdup ("?:");
00523     $$->nargs = 3;
00524     $1->append ($3);
00525     $1->append ($5);
00526     $$->args = $1;
00527   }
00528   | Expression Less Expression {
00529     $$ = new eqn::application ();
00530     $$->n = strdup ("<");
00531     $$->nargs = 2;
00532     $1->append ($3);
00533     $$->args = $1;
00534   }
00535   | Expression Greater Expression {
00536     $$ = new eqn::application ();
00537     $$->n = strdup (">");
00538     $$->nargs = 2;
00539     $1->append ($3);
00540     $$->args = $1;
00541   }
00542   | Expression GreaterOrEqual Expression {
00543     $$ = new eqn::application ();
00544     $$->n = strdup (">=");
00545     $$->nargs = 2;
00546     $1->append ($3);
00547     $$->args = $1;
00548   }
00549   | Expression LessOrEqual Expression {
00550     $$ = new eqn::application ();
00551     $$->n = strdup ("<=");
00552     $$->nargs = 2;
00553     $1->append ($3);
00554     $$->args = $1;
00555   }
00556   | Expression Equal Expression {
00557     $$ = new eqn::application ();
00558     $$->n = strdup ("==");
00559     $$->nargs = 2;
00560     $1->append ($3);
00561     $$->args = $1;
00562   }
00563   | Expression NotEqual Expression {
00564     $$ = new eqn::application ();
00565     $$->n = strdup ("!=");
00566     $$->nargs = 2;
00567     $1->append ($3);
00568     $$->args = $1;
00569   }
00570   | Not Expression {
00571     $$ = new eqn::application ();
00572     $$->n = strdup ("!");
00573     $$->nargs = 1;
00574     $$->args = $2;
00575   }
00576   | Expression And Expression {
00577     $$ = new eqn::application ();
00578     $$->n = strdup ("&&");
00579     $$->nargs = 2;
00580     $1->append ($3);
00581     $$->args = $1;
00582   }
00583   | Expression Or Expression {
00584     $$ = new eqn::application ();
00585     $$->n = strdup ("||");
00586     $$->nargs = 2;
00587     $1->append ($3);
00588     $$->args = $1;
00589   }
00590 ;
00591 
00592 ExpressionList: /* nothing */ { $$ = NULL; }
00593   | Expression {
00594     $$ = $1;
00595   }
00596   | Range {
00597     $$ = $1;
00598   }
00599   | Expression ',' ExpressionList {
00600     $1->setNext ($3);
00601     $$ = $1;
00602   }
00603   | Range ',' ExpressionList {
00604     $1->setNext ($3);
00605     $$ = $1;
00606   }
00607 ;
00608 
00609 SubcircuitBody:
00610   DefBegin DefBody DefEnd { /* a full subcircuit definition found */
00611     $1->sub = $2;
00612     $$ = $1;
00613     $2 = NULL;
00614   }
00615 ;
00616 
00617 DefBegin:
00618   DefSub InstanceIdentifier NodeList PairList Eol {
00619     /* create subcircuit definition right here */
00620     $$ = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
00621     $$->type = strdup ("Def");
00622     $$->instance = $2;
00623     $$->nodes = $3;
00624     $$->pairs = $4;
00625     $$->action = PROP_ACTION;
00626     $$->line = netlist_lineno;
00627   }
00628 ;
00629 
00630 DefBody: /* nothing */ { $$ = NULL; }
00631   | DefBodyLine DefBody { /* chain definitions here */
00632     if ($1) {
00633       $1->next = $2;
00634       $$ = $1;
00635     }
00636     else {
00637       $$ = $2;
00638     }
00639   }
00640 ;
00641 
00642 DefEnd:
00643   EndSub Eol { /* nothing to do */ }
00644 ;
00645 
00646 DefBodyLine:
00647   DefinitionLine { /* chain definitions here */
00648     $1->next = $$;
00649     $$ = $1;
00650   }
00651   | EquationLine { /* chain definitions here */
00652     $1->next = $$;
00653     $$ = $1;
00654   }
00655   | SubcircuitBody { /* do nothing here, see subcircuit rule */ }
00656   | Eol {
00657     $$ = NULL;
00658   }
00659 ;
00660 
00661 
00662 %%
00663 
00664 int netlist_error (const char * error) {
00665   logprint (LOG_ERROR, "line %d: %s\n", netlist_lineno, error);
00666   return 0;
00667 }