1 ''' @file apg_py/lib/trace.py @brief Displays a trace of the parse tree.
2 The trace is a printed description of each
3 parse tree node processed by the parser.
16 '''Class for tracing and displaying the progress
17 of the parser through the parse tree.
18 The Trace class has a copy of the Parser class and knows how to use it.
19 Therefore, Trace and Parser need to remain in sync throughout
22 def __init__(self, parser, fname=None, mode='dc', line_max=32):
24 @param parser The parser to trace.
25 @param fname If present, the file name to write the trace to.
26 @param mode The display mode.
27 - 'x' Display characters as hexadecimal digits. e.g. x2e.
28 - 'xc' Display all characters 32-127 as ASCII characters,
29 otherwise use hexadecimal digit display.
30 - 'd' Display characters as decimal digits. e.g. 32.
31 - 'dc' (default) Display all characters 32-127 as ASCII characters,
32 otherwise use decimal digit display.
33 @param line_max The maximum line length in characters
37 if(mode
not in [
'x',
'xc',
'd',
'dc']):
38 raise Exception(
'mode must be one of x, d, xc, dc: found: ', mode)
43 self.
filefile = open(fname,
"w")
70 '''Destructor for ensuring that the output file is closed, if any.'''
71 if(self.
filefile
and self.
filefile != sys.stdout):
77 '''Guarantee that the output file is flushed.'''
82 '''Set the maximum trace line display length in characters.
83 @param max_len The maximum number of characters to
85 self.
line_maxline_max = max(0, max_len)
88 '''For internal use only.'''
95 '''For internal use only.'''
96 return 'ALT(' + str(
len(op[
'children'])) +
')'
99 '''For internal use only.'''
100 return 'CAT(' + str(
len(op[
'children'])) +
')'
103 '''For internal use only.'''
104 rep_max = str(op[
'max']) if(op[
'max'] < id.MAX_INT)
else 'inf'
105 return 'REP(' + str(op[
'min']) +
',' + rep_max +
')'
108 '''For internal use only.'''
109 rule = self.
parserparser.rules[op[
'index']]
110 return 'RNM(' + rule[
'name'] +
')'
113 '''For internal use only.'''
114 udt = self.
parserparser.udts[op[
'index']]
115 return 'UDT(' + udt[
'name'] +
')'
118 '''For internal use only.'''
119 tChars = min(3,
len(op[
'string']))
120 tEnd =
'...' if(
len(op[
'string']) > tChars)
else ''
122 for i
in range(tChars):
125 display += str(op[
'string'][i])
126 return 'TLS(' + display + tEnd +
')'
129 '''For internal use only.'''
130 tChars = min(3,
len(op[
'string']))
131 tEnd =
'...' if(
len(op[
'string']) > tChars)
else ''
133 for i
in range(tChars):
136 display += str(op[
'string'][i])
137 return 'TBS(' + display + tEnd +
')'
140 '''For internal use only.'''
141 return 'TRG(' + str(op[
'min']) +
',' + str(op[
'max']) +
')'
144 '''For internal use only.'''
148 '''For internal use only.'''
152 '''For internal use only.'''
154 if(op[
'bkr_case'] == id.BKR_MODE_CS):
157 if(op[
'bkr_mode'] == id.BKR_MODE_RM):
159 return 'BKR(\\' + case + mode + op[
'name'] +
')'
162 '''For internal use only.'''
166 '''For internal use only.'''
170 '''For internal use only.'''
174 '''For internal use only.'''
178 '''For internal use only.'''
184 ret += (
'x%02x' % dig)
189 '''For internal use only.'''
192 prev_not_ascii =
True
194 if(dig >= 32
and dig < 127):
195 if(count > 0
and prev_not_ascii):
197 prev_not_ascii =
False
202 ret += (
'x%02x' % dig)
203 prev_not_ascii =
True
208 '''For internal use only.'''
219 '''For internal use only.'''
222 prev_not_ascii =
True
224 if(dig >= 32
and dig < 127):
225 if(count > 0
and prev_not_ascii):
227 prev_not_ascii =
False
233 prev_not_ascii =
True
238 '''For internal use only.'''
239 msg =
'state must be ACTIVE on downward transversal of node'
240 assert(self.
parserparser.state == id.ACTIVE), msg
241 if(self.
parserparser.current_look_direction == id.LOOKAROUND_BEHIND):
245 fn = self.
selectOpselectOp.get(op[
'type'])
251 self.
parserparser.sub_end,
252 self.
parserparser.phrase_index +
254 line_end =
'' if(phraseEnd == self.
parserparser.sub_end)
else '...'
255 phrase = self.
parserparser.input[
256 self.
parserparser.phrase_index:phraseEnd]
258 assert(charFormat
is not None),
'invalid mode found in trace down'
259 ret += charFormat(phrase)
261 self.
filefile.write(ret +
'\n')
263 def up(self, op, begin_index):
264 '''For internal use only.'''
265 msg =
'ACTIVE state not allowed on upward transversal of node'
266 state = self.
parserparser.state
267 assert(state != id.ACTIVE), msg
268 if(self.
parserparser.current_look_direction == id.LOOKAROUND_BEHIND):
270 phrase_length = begin_index - self.
parserparser.phrase_index
271 phrase_length = min(phrase_length, self.
line_maxline_max)
272 phrase_index = self.
parserparser.phrase_index
275 phrase_length = self.
parserparser.phrase_index - begin_index
276 phrase_length = min(phrase_length, self.
line_maxline_max)
277 phrase_index = self.
parserparser.phrase_index - phrase_length
279 stateDisplay = id.dict.get(state,
None)[0]
280 assert(stateDisplay
is not None),
'invalid state found in trace.up()'
281 ret +=
'|' + stateDisplay +
'|' + \
282 str(phrase_length) +
'|'
283 fn = self.
selectOpselectOp.get(op[
'type'])
285 if(state == id.MATCH):
288 phrase_length < phrase_length)
else ''
289 phrase = self.
parserparser.input[phrase_index:
290 phrase_index + phrase_length]
292 assert(charFormat
is not None),
'invalid mode found in trace down'
293 ret += charFormat(phrase)
295 elif(state == id.EMPTY):
297 self.
filefile.write(ret +
'\n')
Class for tracing and displaying the progress of the parser through the parse tree.
def phrased(self, phrase)
For internal use only.
def down(self, op)
For internal use only.
def traceNOT(self, op)
For internal use only.
def traceBKA(self, op)
For internal use only.
def set_display_length(self, max_len)
Set the maximum trace line display length in characters.
def traceAND(self, op)
For internal use only.
def traceCAT(self, op)
For internal use only.
def __init__(self, parser, fname=None, mode='dc', line_max=32)
def traceAEN(self, op)
For internal use only.
def traceUDT(self, op)
For internal use only.
def traceBKR(self, op)
For internal use only.
def finish(self)
Guarantee that the output file is flushed.
def traceTBS(self, op)
For internal use only.
def __del__(self)
Destructor for ensuring that the output file is closed, if any.
def traceTRG(self, op)
For internal use only.
def up(self, op, begin_index)
For internal use only.
def traceTLS(self, op)
For internal use only.
def traceABG(self, op)
For internal use only.
def phrasex(self, phrase)
For internal use only.
def indent(self, n)
For internal use only.
def traceREP(self, op)
For internal use only.
def phrasedc(self, phrase)
For internal use only.
def traceBKN(self, op)
For internal use only.
def phrasexc(self, phrase)
For internal use only.
def traceRNM(self, op)
For internal use only.
def traceALT(self, op)
For internal use only.