1/*
2 * cdlParser.yy
3 *
4 * Copyright 2014-2018 D. Mitch Bailey  cvc at shuharisystem dot com
5 *
6 * This file is part of cvc.
7 *
8 * cvc is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * cvc is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with cvc.  If not, see <http://www.gnu.org/licenses/>.
20 *
21 * You can download cvc from https://github.com/d-m-bailey/cvc.git
22*/
23
24%skeleton "lalr1.cc"
25%require "3.0"
26
27%define parser_class_name {CCdlParser}
28
29%define parse.assert
30
31%code requires {
32#include "Cvc.hh"
33
34#include "CCircuit.hh"
35#include "CDevice.hh"
36
37class CCdlParserDriver;
38
39#define YYDEBUG 1
40}
41
42// The parsing context.
43%param { CCdlParserDriver& driver } { CCircuitPtrList& cdlCircuitList } { bool theCvcSOI }
44
45%locations
46%initial-action
47{
48// Initialize the initial location.
49@$.initialize(&driver.filename);
50};
51
52%define parse.trace
53%define parse.error verbose
54
55%code
56{
57#include "CCdlParserDriver.hh"
58}
59
60%union { string * StringPtr; }
61%union { char * charPtr; }
62
63%token CDL_EOF 0 "END-OF-FILE"
64%token SUBCKT "SUBCKT"
65%token ENDS "ENDS"
66%token <charPtr> SUBCIRCUIT
67%token <charPtr> BIPOLAR
68%token <charPtr> CAPACITOR
69%token <charPtr> DIODE
70%token <charPtr> MOSFET
71%token <charPtr> RESISTOR
72%token <charPtr> INDUCTOR
73%token <charPtr> STRING
74%token EOL "EOL"
75
76%union { void * VoidPtr; }
77%type <VoidPtr> circuitList
78
79%union { CCircuit * CircuitPtr; }
80%type <CircuitPtr> circuit
81
82%union { CTextList * charPtrListPtr; }
83%type <charPtrListPtr> stringList
84%type <charPtrListPtr> interface
85
86%union { CDevicePtrList *DevicePtrListPtr; }
87%type <DevicePtrListPtr> deviceList
88
89%union { CDevice * DevicePtr; }
90%type <DevicePtr> device
91%type <DevicePtr> subcircuit
92%type <DevicePtr> bipolar
93%type <DevicePtr> capacitor
94%type <DevicePtr> diode
95%type <DevicePtr> inductor
96%type <DevicePtr> mosfet
97%type <DevicePtr> resistor
98
99/*
100%printer { yyoutput << $$; } <*>;
101%printer { yyoutput << "\"" << $$->c_str << "\""; } <StringPtr>;
102%printer { yyoutput << "<>"; } <>;
103*/
104
105%%
106
107%start circuitList;
108
109circuitList[after]:
110	%empty {
111		$after = NULL;
112	};
113|	circuitList[before] circuit {
114		if ( $circuit != NULL ) {
115	//		$circuit->Print();
116			cdlCircuitList.push_back($circuit);
117			cdlCircuitList.circuitNameMap[$circuit->name] = $circuit;
118		}
119	};
120
121circuit:
122	SUBCKT interface ENDS EOL {
123/**/
124		$circuit = new CCircuit();
125		$circuit->name = $interface->front();
126		$interface->pop_front();
127		$circuit->AddPortSignalIds($interface);
128/**/
129		delete $interface;
130//		$circuit = NULL;
131	}
132|	SUBCKT interface deviceList ENDS EOL {
133		$circuit = new CCircuit();
134		$circuit->name = $interface->front();
135		$interface->pop_front();
136		$circuit->AddPortSignalIds($interface);
137		delete $interface;
138//		$circuit->devices = $deviceList;
139		$circuit->LoadDevices($deviceList);
140//		delete $deviceList;
141//		for (CDeviceList::iterator current = $circuit->devices->begin(); current != $circuit->devices->end(); current++ ) {
142//			current->signalIndexVector = $circuit->SetSignalIndexes(current->signals);
143//			delete current->signals;
144//		}
145		delete $deviceList;
146	};
147
148interface:
149	stringList EOL;
150
151stringList[after]:
152	STRING {
153		$after = new CTextList();
154		$after->push_back($STRING);
155	}
156|	stringList[before] STRING {
157		$before->push_back($STRING);
158	};
159
160deviceList[after]:
161	device {
162//		$after = new CDevicePtrList(1, *$device);
163		$after = new CDevicePtrList();
164		if ( $device != NULL ) {
165			if ( $device->IsSubcircuit() ) {
166				$after->subcircuitCount++;
167			}
168			$after->push_back($device);
169		}
170	}
171|	deviceList[before] device {
172		if ( $device != NULL ) {
173			if ( $device->IsSubcircuit() ) {
174				$before->subcircuitCount++;
175			}
176			$before->push_back($device);
177		}
178	};
179
180device:
181	subcircuit {}
182|	bipolar {}
183|	capacitor {}
184|	diode {}
185|	inductor {}
186|	mosfet {}
187|	resistor {};
188
189subcircuit:
190	SUBCIRCUIT stringList EOL {
191//		printf("** NOERROR: found subckt: %s\n", $SUBCIRCUIT);
192		$subcircuit = new CDevice();
193		$subcircuit->name = $SUBCIRCUIT;
194		char * myString = $stringList->back();
195		$stringList->pop_back();
196		CTextList * myParameterList = new CTextList;
197		while( strchr(myString, '=') ) {
198			myParameterList->push_front(myString);
199			myString = $stringList->back();
200			$stringList->pop_back();
201		}
202		$subcircuit->masterName = myString;
203		$subcircuit->signalList_p = $stringList;
204		if ( ! myParameterList->empty() ) {
205			myParameterList->push_front(myString);  // add box model name
206			$subcircuit->parameters = cdlCircuitList.parameterText.SetTextAddress("X", myParameterList);
207		}
208		delete myParameterList;
209	};
210
211bipolar:
212	BIPOLAR STRING[collector] STRING[base] STRING[emitter] stringList EOL {
213/*
214		printf("** ERROR: bipolar device not supported: %s\n", $BIPOLAR);
215		cdlCircuitList.errorCount++;
216		$bipolar = NULL;
217*/
218/**/
219		$bipolar = new CDevice();
220		$bipolar->name = $BIPOLAR;
221		$bipolar->signalList_p = new CTextList();
222		$bipolar->AppendSignal($collector);
223		$bipolar->AppendSignal($base);
224		$bipolar->AppendSignal($emitter);
225		$bipolar->parameters = cdlCircuitList.parameterText.SetTextAddress("Q", $stringList);
226/**/
227		delete $stringList;
228};
229
230capacitor:
231	CAPACITOR STRING[plus] STRING[minus] stringList EOL {
232		$capacitor = new CDevice();
233		$capacitor->name = $CAPACITOR;
234		$capacitor->signalList_p = new CTextList();
235		$capacitor->AppendSignal($plus);
236		$capacitor->AppendSignal($minus);
237		$capacitor->AppendSignal($stringList->BiasNet(cdlCircuitList.cdlText));
238/*
239		if ( $stringList->BiasNet(cdlCircuitList.cdlText) ) {
240			printf("** Warning: three terminal capacitor not supported: %s\n", $CAPACITOR);
241			cdlCircuitList.warningCount++;
242		}
243*/
244		$capacitor->parameters = cdlCircuitList.parameterText.SetTextAddress("C", $stringList);
245		delete $stringList;
246	};
247
248diode:
249	DIODE STRING[anode] STRING[cathode] stringList EOL {
250		$diode = new CDevice();
251		$diode->name = $DIODE;
252		$diode->sourceDrainSet = true;
253		$diode->sourceDrainSwapOk = false;
254		$diode->signalList_p = new CTextList();
255		$diode->AppendSignal($anode);
256		$diode->AppendSignal($cathode);
257		$diode->parameters = cdlCircuitList.parameterText.SetTextAddress("D", $stringList);
258		delete $stringList;
259	};
260
261inductor:
262	INDUCTOR STRING[plus] STRING[minus] stringList EOL {
263		printf("** ERROR: inductor device not supported: %s\n", $INDUCTOR);
264		cdlCircuitList.errorCount++;
265		$inductor = NULL;
266	/*
267		$inductor = new CDevice();
268		$inductor->name = $INDUCTOR;
269		$inductor->AppendSignal($plus);
270		$inductor->AppendSignal($minus);
271		$inductor->parameters = cdlCircuitList.parameterText.SetTextAddress($stringList);
272	*/
273		delete $stringList;
274	};
275
276mosfet:
277	MOSFET STRING[drain] STRING[gate] STRING[source] STRING[bulk] stringList EOL {
278		$mosfet = new CDevice();
279		$mosfet->name = $MOSFET;
280		$mosfet->signalList_p = new CTextList();
281		$mosfet->AppendSignal($drain);
282		$mosfet->AppendSignal($gate);
283		$mosfet->AppendSignal($source);
284		if ( ! theCvcSOI ) {
285			$mosfet->AppendSignal($bulk);
286		}
287		$mosfet->parameters = cdlCircuitList.parameterText.SetTextAddress("M", $stringList);
288		delete $stringList;
289	};
290
291resistor:
292	RESISTOR STRING[plus] STRING[minus] stringList EOL {
293		$resistor = new CDevice();
294		$resistor->name = $RESISTOR;
295		$resistor->signalList_p = new CTextList();
296		$resistor->AppendSignal($plus);
297		$resistor->AppendSignal($minus);
298		$resistor->AppendSignal($stringList->BiasNet(cdlCircuitList.cdlText));
299/*
300		if ( $stringList->BiasNet(cdlCircuitList.cdlText) ) {
301			printf("** Warning: three terminal resistor not supported: %s\n", $RESISTOR);
302			cdlCircuitList.warningCount++;
303		}
304*/
305		$resistor->parameters = cdlCircuitList.parameterText.SetTextAddress("R", $stringList);
306		delete $stringList;
307	};
308
309%%
310
311void
312yy::CCdlParser::error (const yy::location& l, const string& m)
313{
314	driver.error (l, m);
315}
316