source: CIVL/mods/dev.civl.com/scripts/state_space_parser.py@ a7752a9

main test-branch
Last change on this file since a7752a9 was c2b37db, checked in by Alex Wilton <awilton@…>, 8 months ago

Merged focus branch into trunk.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5988 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[c2b37db]1import sys
2from dataclasses import dataclass
3
4from state_space import *
5from lexical_stream import *
6
7def createTransition(stateSpace, contentStr, pid, fromState, toState):
8 transition = Transition(contentStr, pid, fromState, toState)
9 stateSpace.addTransition(transition)
10 return transition
11
12@dataclass(frozen=True)
13class StartTransitionToken:
14 pid: int
15 fromStateID: StateID
16
17@dataclass(frozen=True)
18class SubTransitionToken:
19 contentStr: str
20
21@dataclass(frozen=True)
22class StopTransitionToken:
23 toStateID: StateID
24
25class StateTerminal:
26 first = "State"
27
28 pattern = r"(\d+(?:\.\d+)?) \(id=(\d+)\)"
29
30 def parseHead(file):
31 file.start()
32 try:
33 file.match(StateTerminal.first)
34 file.skipws()
35 file.match("(")
36 leftID = int(file.regmatch(r"\d+").group(0))
37 if file.match("."):
38 rightID = int(file.regmatch(r"\d+").group(0))
39 file.match(")")
40 else:
41 rightID = 0
42 file.skipws()
43 file.match("(id=")
44 uniqueID = int(file.regmatch(r"\d+").group(0))
45 file.match(")")
46 except Exception as err:
47 file.revert()
48 print(err)
49 raise ParseError(file.pos().lineNum)
50
51 return file.complete(), StateID(leftID, rightID, uniqueID)
52
53 def parseFrameEntry(file):
54 file.start()
55 try:
56 if not file.match("| | | | Frame[function="):
57 file.revert()
58 return None
59
60 functionName = file.regmatch(r"[^\s,]+").group(0)
61 file.match(", location=")
62
63 location = int(file.regmatch(r"\d+").group(0))
64 file.match(", ")
65
66 match = file.regmatch(r"(.+), dyscope=d(\d+)\]\n$")
67 source = match.group(1)
68 dyscope = int(match.group(2))
69
70 return file.complete(), FrameEntry(functionName, location, source, dyscope)
71 except Exception as err:
72 file.revert()
73 print(err)
74 raise ParseError(file.pos().lineNum)
75
76 def parseProcessState(file):
77 file.start()
78 try:
79 if not file.match("| | process "):
80 file.revert()
81 return None
82
83 procMatch = file.regmatch(r"\d+")
84 file.skipws()
85 procId = int(procMatch.group(0))
86
87 atomicCount = 0
88 if file.match("| | | atomicCount="):
89 atomicCount = int(file.regmatch(r"\d+"))
90 file.skipws()
91
92 if not file.match("| | | call stack"):
93 raise Exception("Expected call stack")
94 file.skipws()
95
96 frames = []
97 while (tuple := StateTerminal.parseFrameEntry(file)):
98 _, frameEntry = tuple
99 frames.append(frameEntry)
100
101 return file.complete(), ProcessState(procId, atomicCount, frames)
102 except Exception as err:
103 file.revert()
104 print(err)
105 raise ParseError(file.pos().lineNum)
106
107 def parse(file):
108 headRange, sid = StateTerminal.parseHead(file)
109 file.skipws()
110 contentStr = ""
111 reachedEmptySpace = False
112 procStateLine = "| Process states\n"
113
114 while not file.match(procStateLine) and not file.eof():
115 contentStr += file.readline()
116 contentStr += procStateLine
117
118 procStates = []
119 while (tuple := StateTerminal.parseProcessState(file)):
120 procStateRange, procState = tuple
121 contentStr += procStateRange.getStr()
122 procStates.append(procState)
123
124 return State(headRange.getStr().strip(), contentStr, sid, procStates)
125
126class StartTransitionTerminal:
127 first = "Executed"
128
129 def parse(file):
130 file.start()
131 try:
132 file.match(StartTransitionTerminal.first)
133 file.skipws()
134 file.match("by")
135 file.skipws()
136 file.match("p")
137 procID = int(file.regmatch(r"\d+").group(0))
138 file.skipws()
139 file.match("from")
140 file.skipws()
141 _, fromStateID = StateTerminal.parseHead(file)
142 except Exception:
143 file.revert()
144 raise ParseError(file.pos().lineNum)
145
146 file.complete()
147 return StartTransitionToken(procID, fromStateID)
148
149class SubTransitionTerminal:
150 first = r"\d+->(\d+|RET):"
151
152 def parse(file):
153 return SubTransitionToken(file.readline())
154
155class StopTransitionTerminal:
156 first = "-->"
157
158 def parse(file):
159 file.start()
160 try:
161 file.match(StopTransitionTerminal.first)
162 file.skipws()
163 _, toStateID = StateTerminal.parseHead(file)
164 except Exception:
165 file.revert()
166 raise ParseError(file.pos().lineNum)
167
168 file.complete()
169 return StopTransitionToken(toStateID)
170
171def parseTerminal(file, *potentialTerms):
172 for terminal in potentialTerms:
173 if file.peek(terminal.first):
174 return terminal.parse(file)
175 return None
176
177def parseInitState(file, stateSpace):
178 try:
179 while not (initState := parseTerminal(file, StateTerminal)) and not file.eof():
180 file.readline()
181 except ParseError as err:
182 print("Parsing error: Failed to parse initial state.", err)
183
184 if not initState:
185 print("No States found.")
186 return
187
188 stateSpace.addInitState(initState)
189
190def parseState(file, stateSpace):
191 try:
192 return parseTerminal(file, StateTerminal)
193 except ParseError as err:
194 print("Parsing error: Failed to parse initial state.", err)
195 raise
196
197def parseStartTransition(file):
198 try:
199 return parseTerminal(file, StartTransitionTerminal)
200 except ParseError as err:
201 print("Parsing error: Failed to parse transition", err)
202 raise
203
204def parseSubTransition(file):
205 try:
206 if not (subTransToken := parseTerminal(file, SubTransitionTerminal)):
207 raise ParseError(file.pos().lineNum)
208 return subTransToken
209 except ParseError as err:
210 print("Parsing error: Failed to parse sub transition", err)
211 raise
212
213def parseStopTransition(file):
214 try:
215 if not (stopToken := parseTerminal(file, StopTransitionTerminal)):
216 raise ParseError(file.pos().lineNum)
217 return stopToken
218 except ParseError as err:
219 print("Parsing error: Failed to parse sub transition", err)
220 raise
221
222def parseLargeTransitionStep(file, stateSpace):
223 if not (startToken := parseStartTransition(file)):
224 return False
225 lastState = stateSpace.getState(startToken.fromStateID)
226
227 file.skipws()
228 subTransToken = parseSubTransition(file)
229
230 file.skipws()
231 while (nextState := parseState(file, stateSpace)):
232 newTransition = createTransition(stateSpace, subTransToken.contentStr, startToken.pid, lastState, nextState)
233 lastState = nextState
234
235 file.skipws()
236 subTransToken = parseSubTransition(file)
237
238 file.skipws()
239 stopToken = parseStopTransition(file)
240
241 file.skipws()
242 if not (endState := parseState(file, stateSpace)):
243 endState = stateSpace.getState(stopToken.toStateID)
244 lastTransition = createTransition(stateSpace, subTransToken.contentStr, startToken.pid, lastState, endState)
245
246 return True
247
248def parseStateSpace(fileName):
249 stateSpace = StateSpace()
250
251 with open(fileName, 'r', encoding="utf-8") as f:
252 file = LexicalStream(f)
253 try:
254 parseInitState(file, stateSpace)
255 file.skipws()
256 while parseLargeTransitionStep(file, stateSpace):
257 file.skipws()
258 except ParseError:
259 pass
260
261 return stateSpace
Note: See TracBrowser for help on using the repository browser.