1 # Copyright (C) 2019 Nick Downing <nick@ndcode.org>
2 # SPDX-License-Identifier: GPL-2.0-with-bison-exception
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; version 2.
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 # As a special exception, you may create a larger work that contains part or
18 # all of the pilex lexical scanner skeleton and distribute that work under
19 # terms of your choice, so long as that work isn't itself a lexical scanner
20 # generator using the skeleton or a modified version thereof as a lexical
21 # scanner skeleton. Alternatively, if you modify or redistribute the lexical
22 # scanner skeleton itself, you may (at your option) remove this special
23 # exception, which will cause the skeleton and the resulting pilex output
24 # files to be licensed under the GNU General Public License without this
29 from ndcode.piyacc import element
31 # this can be redefined in SECTION1
33 return yy_buffer_stack[-1].at_bol
35 def yy_set_bol(at_bol):
36 yy_buffer_stack[-1].at_bol = at_bol
42 # note that this should also be done after yyless() and REJECT(),
43 # and state should be saved in case they result in a null string,
44 # however, it doesn't seem to be in flex, maintain compatibility:
46 yy_set_bol(yytext[-1] == '\n')
51 # GENERATE STARTCONDDECL
53 class YYReject(Exception):
56 class YYContinue(Exception):
59 class YYTerminate(Exception):
63 def __init__(self, next = None):
66 class YYBufferBlock(YYBufferList):
67 def __init__(self, next = None, pos = 0, text = ''):
68 YYBufferList.__init__(self, next)
72 class YYBufferState(YYBufferList):
73 def __init__(self, next = None, file_in = None, at_bol = True):
74 YYBufferList.__init__(self, next)
75 self.file_in = file_in
80 yy_buffer_stack = [YYBufferState()]
91 yy_groups_by_name = None
96 yy_element_stack = None
97 yy_element_token = None
98 yy_element_space = None
109 global yytext, yytext_len
110 assert yytext_len >= i
115 global yyin, yytext_len
117 block = yy_buffer_stack[-1].next
118 while block is None or block.pos >= len(block.text):
120 yy_buffer_stack.pop()
121 block = yy_buffer_stack[-1].next
122 yyin = yy_buffer_stack[-1].file_in
125 yy_buffer_stack[-1].next = block
126 i = min(yytext_len, len(block.text) - block.pos)
129 yy_buffer_stack[-1].next = YYBufferBlock(yy_buffer_stack[-1].next, 0, text)
135 global yytext, yytext_len, yy_element_stack
136 yytext = yy_group_text[:yy_group_stack[-1]]
137 yytext_len = yy_group_stack[-1]
138 del yy_group_stack[-2:]
140 yy_element_stack.append([])
145 def yy_group_end_element():
146 yy_element_stack.append([])
148 def yy_group_element(pos0, pos1, stack, _class, *args, **kwargs):
149 _element = _class(*args, **kwargs)
151 for pos2, pos3, i in reversed(stack):
152 _element.text.append(yy_group_text[pos0:pos2])
153 _element.children.append(i)
155 _element.text.append(yy_group_text[pos0:pos1])
165 def yy_push_state(start):
167 yystart_stack.append(yystart)
172 yystart = yystart_stack.pop()
176 def yylex(_class = element.Element, *args, **kwargs):
191 # GENERATE SECTION2INITIAL
193 yy_element_space = _class(*args, **kwargs)
194 yy_element_token = _class(*args, **kwargs)
197 block = yy_buffer_stack[-1].next
198 while block is None or block.pos >= len(block.text):
200 yy_buffer_stack.pop()
201 block = yy_buffer_stack[-1].next
202 yyin = yy_buffer_stack[-1].file_in
205 yy_buffer_stack[-1].next = block
206 i = min(yytext_len, len(block.text) - block.pos)
213 del yy_threads0[yy_prefix_slop:]
214 yy_threads0.append(None)
216 buffer_ptr = len(yy_buffer_stack) - 1
217 block_prev = yy_buffer_stack[buffer_ptr]
218 block = block_prev.next
219 if block is not None:
220 block_pos = block.pos
222 action = yy_dfa_start_action[
223 yystart * 2 + int(yy_buffer_stack[-1].at_bol)
226 state, transition = yy_dfa_actions[action]
227 #print('i', i, 'action', action, 'state', state, 'transition', transition)
230 assert len(yy_threads1) == yy_prefix_slop
231 for trans in transition:
232 if trans[0] == 0: #DFA.TRANSITION_POP:
234 elif trans[0] == 1: #DFA.TRANSITION_DUP:
236 yy_threads0[:0] = [None] * yy_prefix_slop
237 yy_threads1[:0] = [None] * yy_prefix_slop
240 yy_threads0[i - trans[1]:i] = yy_threads0[i:i + trans[1]]
242 elif trans[0] == 2: #DFA.TRANSITION_MARK:
243 yy_threads0[i:i + trans[1]] = [
244 (match_len, trans[2], thread)
245 for thread in yy_threads0[i:i + trans[1]]
247 elif trans[0] == 3: #DFA.TRANSITION_MOVE:
248 yy_threads1.extend(yy_threads0[i:i + trans[1]])
250 #elif trans[0] == DFA.TRANSITION_DEL:
251 # del yy_threads1[-trans[1]:]
254 assert i == len(yy_threads0)
255 yy_threads0, yy_threads1 = yy_threads1, yy_threads0
256 del yy_threads1[yy_prefix_slop:]
259 # there is only one match, which is complete
260 assert len(yy_threads0) == yy_prefix_slop + 1
261 assert yy_dfa_states[state][2] == [0]
264 yy_buffer_stack[-1].file_in = yyin
265 while block is None or block_pos >= len(block.text):
267 file_in = yy_buffer_stack[buffer_ptr].file_in
268 text = '' if file_in is None else file_in.readline()
270 block = YYBufferBlock(None, 0, text)
272 block_prev.next = block
274 # do not re-attempt read once EOF is reached
275 yy_buffer_stack[buffer_ptr].file_in = None
276 yyin = yy_buffer_stack[-1].file_in
280 block_prev = yy_buffer_stack[buffer_ptr]
281 block = block_prev.next
282 if block is not None:
283 block_pos = block.pos
285 i = match_len - len(match)
287 match += block.text[block_pos - i:]
289 block = block_prev.next
290 if block is not None:
291 block_pos = block.pos
293 #print('block_pos', block_pos, 'block.text', block.text)
294 action = yy_dfa_states[state][1][
296 yy_dfa_states[state][0],
297 ord(block.text[block_pos])
306 return yy_eof_actions[yystart]()
311 i = match_len - len(match)
313 assert block is not None
314 match += block.text[block_pos - i:]
316 for i in yy_dfa_states[state][2]:
317 yy_group_text = match
320 yy_groups_by_name = None
324 yy_element_stack = []
326 thread = yy_threads0[yy_prefix_slop + i]
327 #print('thread', thread)
328 while thread is not None:
329 pos, ref_data, thread = thread
330 yy_group_stack.append(pos)
333 yy_element_token = yy_group_element(
336 yy_element_stack.pop(),
351 raise Exception('scanner jammed')
353 # append yy_element_token contents onto yy_element_space
354 assert len(yy_element_space.text) == len(yy_element_space.children) + 1
355 assert len(yy_element_token.text) == len(yy_element_token.children) + 1
356 yy_element_space.text[-1] += yy_element_token.text[0]
357 yy_element_space.children.extend(yy_element_token.children)
358 yy_element_space.text.extend(yy_element_token.text[1:])
360 # clear yy_element_token for next yytext or EOF action
361 del yy_element_token.text[1:]
362 del yy_element_token.children[:]