-
Notifications
You must be signed in to change notification settings - Fork 0
/
SpiceVarExpr.py
150 lines (124 loc) · 5.73 KB
/
SpiceVarExpr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
from fysom import Fysom
from tokenize import generate_tokens, NAME, NUMBER, OP, ENDMARKER
from io import StringIO
class SpiceVarExpr:
def __init__(self):
self.outExpr= ''
self.waveType= ''
self.waveName= ''
self.datasetName= 'r'
self.fsm = Fysom({'initial': 'looking',
'events':
[
{'name': 'seeWaveVar', 'src':'looking', 'dst':'openParen'},
{'name': 'seeOpenParen', 'src':'openParen', 'dst':'inWaveVar'},
{'name': 'getWaveVar', 'src':'inWaveVar', 'dst':'closeParen'},
{'name': 'seeCloseParen', 'src':'closeParen', 'dst':'looking'},
{'name': 'reset', 'src':['looking', 'openParen', 'inWaveVar', 'closeParen'], 'dst':'looking'}
],
'callbacks':{
'onseeWaveVar': self.onseeWaveVar,
'ongetWaveVar': self.ongetWaveVar,
'onseeCloseParen': self.onseeCloseParen,
}
})
def datasetName(self, datasetName):
self.dataset= datasetName
def onseeWaveVar(self, e):
self.waveType= e.msg
def ongetWaveVar(self, e):
self.waveName= e.msg
def onseeCloseParen(self, e):
self.outExpr += self.datasetName + "." + self.waveType + "('" + self.waveName + "')"
# The state machine makes sure that the voltage or current expression follows the syntax.
# If it doesn't, the machine backtracks and resets.
# The non-matching text passes through.
# Backtracking could be implemented with untokenize()
# Problem: the tokenizer is not returning x1.3, it is returning x1.
# Then the closing parenthesis, which is expected next, is not found.
# This causes the state machine to backtrack and not translate to r['x1.3'] as it should.
# Need to either fix the generate_tokens or the state machine to know to be able to
# take more tokens to add to the state 'inWaveVar' before the closing paren.
# Since generate_tokens is a big complicated module that someone else did,
# need to handle the states here.
#
# This routine returns whitespace, which isn't always what is wanted.
def fixWaveFormVariableNames(self, txt):
self.outExpr= ''
lastToknum= 0
g = generate_tokens(StringIO(txt).readline)
try:
for toknum, tokval, _, _, _ in g:
if self.fsm.current == "looking":
if toknum == NAME and (tokval == 'v' or tokval == 'i'):
self.fsm.seeWaveVar(msg=tokval)
continue
elif self.fsm.current == "openParen":
if toknum == OP and tokval == '(':
self.fsm.seeOpenParen(msg=tokval)
continue
else:
self.outExpr += self.waveType
self.fsm.reset()
elif self.fsm.current == 'inWaveVar':
if toknum == NAME or toknum == NUMBER:
self.fsm.getWaveVar(msg=tokval)
continue
else:
self.outExpr += self.waveType + '('
self.fsm.reset()
# This appends subcircuit extended net names while still inside parens.
elif self.fsm.current == 'closeParen' and tokval != ')':
self.waveName += tokval
continue
elif self.fsm.current== 'closeParen':
if toknum == OP and tokval == ')':
self.fsm.seeCloseParen(msg=tokval)
continue
else:
self.outExpr += self.waveType + '(' + self.waveName
self.fsm.reset()
self.outExpr += tokval
if toknum == ENDMARKER:
# If the only difference is that whitespace has been removed, restore the original
out= txt
out = txt.replace(" ", "")
if out == self.outExpr:
return txt
else:
return self.outExpr
else:
print("Unexpected end of token parsing.")
return txt
except:
print("Parsing failed")
return txt
if __name__ == "__main__":
# TODO: learn a python testing framework and use it here
sve= SpiceVarExpr()
inputExpression= 'yellow[20 30]'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)
print("-----")
inputExpression= 'v(1a)+2+v(v1)+av(v2)+vi(i)+i(i)'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)
print("-----")
inputExpression= '3.04m+v1+v(a)+v(b)+i(r1)*10k'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)
inputExpression= ')'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)
inputExpression= 'v(x1.3)'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)
inputExpression= 'i(l.x1.l1)'
outputExpression= sve.fixWaveFormVariableNames(inputExpression)
print("Input: " + inputExpression)
print("Output: " + outputExpression)