Version 1.0
Copyright © 2022 Lowell D. Thomas
Python APG
 … an ABNF Parser Generator
scanner_callbacks.py
Go to the documentation of this file.
1 ''' @file apg_py/api/scanner_callbacks.py
2  @brief All of the callback functions for the scanner parser's AST.'''
3 
4 from apg_py.lib import identifiers as id
5 
6 
7 def scanner_line(state, input, phrase_index, phrase_length, data):
8  '''Add a line to the line catalog.
9  @param state The tranlation state,
10  - SEM_PRE the translation is traversing the node going down
11  - SEM_POST the translation is traversing the node going up
12  @param input The full tuple of input integers.
13  @param phrase_index The index of the first integer in the matched phrase.
14  @param phrase_length The number of integers in the matched phrase.
15  @param data User data that was passed to the AST translation, if any.
16  This is available for the user and is never examined, used or changed
17  by the AST translator.
18  '''
19  if(state == id.SEM_PRE):
20  data['invalid_count'] = 0
21  data['text_length'] = 0
22  else:
23  data['lines'].append({
24  'line_no': data['line_no'],
25  'index': phrase_index,
26  'length': phrase_length,
27  'text_length': data['text_length'],
28  'line_end': data['line_end'],
29  'invalid_chars': data['invalid_count']
30  })
31  return id.SEM_OK
32 
33 
34 def scanner_last_line(state, input, phrase_index, phrase_length, data):
35  '''Deal with a last line with no line ending.
36  @param state The tranlation state,
37  - SEM_PRE the translation is traversing the node going down
38  - SEM_POST the translation is traversing the node going up
39  @param input The full tuple of input integers.
40  @param phrase_index The index of the first integer in the matched phrase.
41  @param phrase_length The number of integers in the matched phrase.
42  @param data User data that was passed to the AST translation, if any.
43  This is available for the user and is never examined, used or changed
44  by the AST translator.
45  '''
46  if(state == id.SEM_PRE):
47  data['invalid_count'] = 0
48  data['text_length'] = 0
49  else:
50  data['lines'].append({
51  'line_no': data['line_no'],
52  'index': phrase_index,
53  'length': phrase_length,
54  'text_length': data['text_length'],
55  'line_end': '',
56  'invalid_chars': data['invalid_count']
57  })
58  msg = 'last line must end with line end character(s)'
59  data['errors'].append({
60  'line': data['line_no'],
61  'index': phrase_index + phrase_length,
62  'msg': msg
63  })
64  return id.SEM_OK
65 
66 
67 def scanner_line_text(state, input, phrase_index, phrase_length, data):
68  '''Capture the line text (integers from beginning of line to end.)
69  @param state The tranlation state,
70  - SEM_PRE the translation is traversing the node going down
71  - SEM_POST the translation is traversing the node going up
72  @param input The full tuple of input integers.
73  @param phrase_index The index of the first integer in the matched phrase.
74  @param phrase_length The number of integers in the matched phrase.
75  @param data User data that was passed to the AST translation, if any.
76  This is available for the user and is never examined, used or changed
77  by the AST translator.
78  '''
79  if(state == id.SEM_PRE):
80  data['text_length'] = phrase_length
81  return id.SEM_OK
82 
83 
84 def scanner_invalid(state, input, phrase_index, phrase_length, data):
85  '''Handle an invalid character.
86  @param state The tranlation state,
87  - SEM_PRE the translation is traversing the node going down
88  - SEM_POST the translation is traversing the node going up
89  @param input The full tuple of input integers.
90  @param phrase_index The index of the first integer in the matched phrase.
91  @param phrase_length The number of integers in the matched phrase.
92  @param data User data that was passed to the AST translation, if any.
93  This is available for the user and is never examined, used or changed
94  by the AST translator.
95  '''
96  if(state == id.SEM_PRE):
97  msg = 'invalid character found: ' \
98  + '\\x%02X' % (input[phrase_index])
99  data['errors'].append({
100  'line': data['line_no'],
101  'index': phrase_index,
102  'msg': msg
103  })
104  return id.SEM_OK
105 
106 
107 def scanner_end(state, input, phrase_index, phrase_length, data):
108  '''Keep track of the current line number.
109  @param state The tranlation state,
110  - SEM_PRE the translation is traversing the node going down
111  - SEM_POST the translation is traversing the node going up
112  @param input The full tuple of input integers.
113  @param phrase_index The index of the first integer in the matched phrase.
114  @param phrase_length The number of integers in the matched phrase.
115  @param data User data that was passed to the AST translation, if any.
116  This is available for the user and is never examined, used or changed
117  by the AST translator.
118  '''
119  if(state == id.SEM_POST):
120  data['line_no'] += 1
121  return id.SEM_OK
122 
123 
124 def scanner_lf(state, input, phrase_index, phrase_length, data):
125  '''Recognize a line feed line ending.
126  @param state The tranlation state,
127  - SEM_PRE the translation is traversing the node going down
128  - SEM_POST the translation is traversing the node going up
129  @param input The full tuple of input integers.
130  @param phrase_index The index of the first integer in the matched phrase.
131  @param phrase_length The number of integers in the matched phrase.
132  @param data User data that was passed to the AST translation, if any.
133  This is available for the user and is never examined, used or changed
134  by the AST translator.
135  '''
136  if(state == id.SEM_PRE):
137  data['line_end'] = 'LF'
138  if(data['strict']):
139  msg = 'strict ABNF specified: ' + \
140  'line end LF(\\x0A) not allowed - must use CRLF(\\x0D0A)'
141  data['errors'].append({
142  'line': data['line_no'],
143  'index': phrase_index,
144  'msg': msg
145  })
146  return id.SEM_OK
147 
148 
149 def scanner_cr(state, input, phrase_index, phrase_length, data):
150  '''Recognize a carriage return line ending.
151  @param state The tranlation state,
152  - SEM_PRE the translation is traversing the node going down
153  - SEM_POST the translation is traversing the node going up
154  @param input The full tuple of input integers.
155  @param phrase_index The index of the first integer in the matched phrase.
156  @param phrase_length The number of integers in the matched phrase.
157  @param data User data that was passed to the AST translation, if any.
158  This is available for the user and is never examined, used or changed
159  by the AST translator.
160  '''
161  if(state == id.SEM_PRE):
162  data['line_end'] = 'CR'
163  if(data['strict']):
164  msg = 'strict ABNF specified: ' + \
165  'line end CR(\\x0D) not allowed - must use CRLF(\\x0D0A)'
166  data['errors'].append({
167  'line': data['line_no'],
168  'index': phrase_index,
169  'msg': msg
170  })
171  return id.SEM_OK
172 
173 
174 def scanner_crlf(state, input, phrase_index, phrase_length, data):
175  '''Recognize a carriage return, line feed combination line ending.
176  @param state The tranlation state,
177  - SEM_PRE the translation is traversing the node going down
178  - SEM_POST the translation is traversing the node going up
179  @param input The full tuple of input integers.
180  @param phrase_index The index of the first integer in the matched phrase.
181  @param phrase_length The number of integers in the matched phrase.
182  @param data User data that was passed to the AST translation, if any.
183  This is available for the user and is never examined, used or changed
184  by the AST translator.
185  '''
186  if(state == id.SEM_PRE):
187  data['line_end'] = 'CRLF'
188  return id.SEM_OK
def scanner_cr(state, input, phrase_index, phrase_length, data)
Recognize a carriage return line ending.
def scanner_end(state, input, phrase_index, phrase_length, data)
Keep track of the current line number.
def scanner_lf(state, input, phrase_index, phrase_length, data)
Recognize a line feed line ending.
def scanner_invalid(state, input, phrase_index, phrase_length, data)
Handle an invalid character.
def scanner_line(state, input, phrase_index, phrase_length, data)
Add a line to the line catalog.
def scanner_line_text(state, input, phrase_index, phrase_length, data)
Capture the line text (integers from beginning of line to end.)
def scanner_last_line(state, input, phrase_index, phrase_length, data)
Deal with a last line with no line ending.
def scanner_crlf(state, input, phrase_index, phrase_length, data)
Recognize a carriage return, line feed combination line ending.
Python APG, Version 1.0, is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.