--- /dev/null
+# Copyright (C) 2019 Nick Downing <nick@ndcode.org>
+# SPDX-License-Identifier: GPL-2.0-with-bison-exception
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+# As a special exception, you may create a larger work that contains part or
+# all of the pilex lexical scanner skeleton and distribute that work under
+# terms of your choice, so long as that work isn't itself a lexical scanner
+# generator using the skeleton or a modified version thereof as a lexical
+# scanner skeleton. Alternatively, if you modify or redistribute the lexical
+# scanner skeleton itself, you may (at your option) remove this special
+# exception, which will cause the skeleton and the resulting pilex output
+# files to be licensed under the GNU General Public License without this
+# special exception.
+
+import bisect
+import element
+import sys
+
+# GENERATE SECTION1
+
+# GENERATE STARTCONDDECL
+
+class YYReject(Exception):
+ pass
+
+class YYContinue(Exception):
+ pass
+
+class YYTerminate(Exception):
+ pass
+
+class YYBufferList:
+ def __init__(self, next = None):
+ self.next = next
+
+class YYBufferBlock(YYBufferList):
+ def __init__(self, next = None, pos = 0, text = ''):
+ YYBufferList.__init__(self, next)
+ self.pos = pos
+ self.text = text
+
+class YYBufferState(YYBufferList):
+ def __init__(self, next = None, file_in = None, at_bol = True):
+ YYBufferList.__init__(self, next)
+ self.file_in = file_in
+ self.at_bol = at_bol
+
+yyin = sys.stdin
+yyout = sys.stdout
+yy_buffer_stack = [YYBufferState()]
+
+yystart = INITIAL
+yystart_stack = []
+yy_threads0 = [None]
+yy_threads1 = [None]
+yy_prefix_slop = 1
+
+yy_group_text = None
+yy_group_stack = None
+yy_groups = None
+yy_groups_by_name = None
+yy_action = None
+yytext = ''
+yytext_len = 0
+
+yy_element_stack = None
+yy_element_token = None
+yy_element_space = None
+
+YY_NULL = 0
+
+def REJECT():
+ raise YYReject()
+
+def yyterminate():
+ raise YYTerminate()
+
+def yyless(i):
+ global yytext, yytext_len
+ assert yytext_len >= i
+ yytext = yytext[:i]
+ yytext_len = i
+
+def unput(text):
+ global yyin, yytext_len
+ while yytext_len:
+ block = yy_buffer_stack[-1].next
+ while block is None or block.pos >= len(block.text):
+ if block is None:
+ yy_buffer_stack.pop()
+ block = yy_buffer_stack[-1].next
+ yyin = yy_buffer_stack[-1].file_in
+ else:
+ block = block.next
+ yy_buffer_stack[-1].next = block
+ i = min(yytext_len, len(block.text) - block.pos)
+ block.pos += i
+ yytext_len -= i
+ yy_buffer_stack[-1].next = YYBufferBlock(yy_buffer_stack[-1].next, 0, text)
+
+def ECHO():
+ yyout.write(yytext)
+
+def yy_rule_start():
+ global yytext, yytext_len, yy_element_stack
+ yytext = yy_group_text[:yy_group_stack[-1]]
+ yytext_len = yy_group_stack[-1]
+ del yy_group_stack[-2:]
+ # note that this should also be done after yyless() and REJECT(),
+ # and state should be saved in case they result in a null string,
+ # however, it doesn't seem to be in flex, maintain compatibility:
+ if len(yytext):
+ yy_buffer_stack[-1].at_bol = yytext[-1] == '\n'
+ yy_element_stack.append([])
+
+def yy_group_end():
+ pass
+
+def yy_group_end_element():
+ yy_element_stack.append([])
+
+def yy_group_element(pos0, pos1, stack, factory, *args, **kwargs):
+ _element = factory(*args, **kwargs)
+ del _element.text[:]
+ for pos2, pos3, i in reversed(stack):
+ _element.text.append(yy_group_text[pos0:pos2])
+ _element.append(i)
+ pos0 = pos3
+ _element.text.append(yy_group_text[pos0:pos1])
+ return _element
+
+def BEGIN(start):
+ global yystart
+ yystart = start
+
+def YY_START():
+ return yystart
+
+def yy_push_state(start):
+ global yystart
+ yystart_stack.append(yystart)
+ yystart = start
+
+def yy_pop_state():
+ global yystart
+ yystart = yystart_stack.pop()
+
+def YY_AT_BOL():
+ return yy_buffer_stack[-1].at_bol
+
+def yy_set_bol(at_bol):
+ yy_buffer_stack[-1].at_bol = at_bol
+
+# GENERATE SECTION2
+
+def yylex(factory = element.Element, *args, **kwargs):
+ global \
+ yyin, \
+ yy_threads0, \
+ yy_threads1, \
+ yy_prefix_slop, \
+ yy_group_text, \
+ yy_group_stack, \
+ yy_action, \
+ yytext, \
+ yytext_len, \
+ yy_element_stack, \
+ yy_element_token, \
+ yy_element_space
+
+ # GENERATE SECTION2INITIAL
+
+ yy_element_space = factory(*args, **kwargs)
+ yy_element_token = factory(*args, **kwargs)
+ while True:
+ while yytext_len:
+ block = yy_buffer_stack[-1].next
+ while block is None or block.pos >= len(block.text):
+ if block is None:
+ yy_buffer_stack.pop()
+ block = yy_buffer_stack[-1].next
+ yyin = yy_buffer_stack[-1].file_in
+ else:
+ block = block.next
+ yy_buffer_stack[-1].next = block
+ i = min(yytext_len, len(block.text) - block.pos)
+ block.pos += i
+ yytext_len -= i
+
+ match = ''
+ match_len = 0
+
+ del yy_threads0[yy_prefix_slop:]
+ yy_threads0.append(None)
+
+ buffer_ptr = len(yy_buffer_stack) - 1
+ block_prev = yy_buffer_stack[buffer_ptr]
+ block = block_prev.next
+ if block is not None:
+ block_pos = block.pos
+
+ action = yy_dfa_start_action[
+ yystart * 2 + int(yy_buffer_stack[-1].at_bol)
+ ]
+ while action != -1:
+ state, transition = yy_dfa_actions[action]
+ #print('i', i, 'action', action, 'state', state, 'transition', transition)
+
+ i = yy_prefix_slop
+ assert len(yy_threads1) == yy_prefix_slop
+ for trans in transition:
+ if trans[0] == 0: #DFA.TRANSITION_POP:
+ i += trans[1]
+ elif trans[0] == 1: #DFA.TRANSITION_DUP:
+ while i < trans[1]:
+ yy_threads0[:0] = [None] * yy_prefix_slop
+ yy_threads1[:0] = [None] * yy_prefix_slop
+ i += yy_prefix_slop
+ yy_prefix_slop *= 2
+ yy_threads0[i - trans[1]:i] = yy_threads0[i:i + trans[1]]
+ i -= trans[1]
+ elif trans[0] == 2: #DFA.TRANSITION_MARK:
+ yy_threads0[i:i + trans[1]] = [
+ (match_len, trans[2], thread)
+ for thread in yy_threads0[i:i + trans[1]]
+ ]
+ elif trans[0] == 3: #DFA.TRANSITION_MOVE:
+ yy_threads1.extend(yy_threads0[i:i + trans[1]])
+ i += trans[1]
+ #elif trans[0] == DFA.TRANSITION_DEL:
+ # del yy_threads1[-trans[1]:]
+ else:
+ assert False
+ assert i == len(yy_threads0)
+ yy_threads0, yy_threads1 = yy_threads1, yy_threads0
+ del yy_threads1[yy_prefix_slop:]
+
+ if state == 0:
+ # there is only one match, which is complete
+ assert len(yy_threads0) == yy_prefix_slop + 1
+ assert yy_dfa_states[state][2] == [0]
+ break
+
+ yy_buffer_stack[-1].file_in = yyin
+ while block is None or block_pos >= len(block.text):
+ if block is None:
+ file_in = yy_buffer_stack[buffer_ptr].file_in
+ text = '' if file_in is None else file_in.readline()
+ if len(text):
+ block = YYBufferBlock(None, 0, text)
+ block_pos = 0
+ block_prev.next = block
+ else:
+ # do not re-attempt read once EOF is reached
+ yy_buffer_stack[buffer_ptr].file_in = None
+ yyin = yy_buffer_stack[-1].file_in
+ buffer_ptr -= 1
+ if buffer_ptr < 0:
+ break # EOF
+ block_prev = yy_buffer_stack[buffer_ptr]
+ block = block_prev.next
+ if block is not None:
+ block_pos = block.pos
+ else:
+ i = match_len - len(match)
+ if i:
+ match += block.text[block_pos - i:]
+ block_prev = block
+ block = block_prev.next
+ if block is not None:
+ block_pos = block.pos
+ else:
+ #print('block_pos', block_pos, 'block.text', block.text)
+ action = yy_dfa_states[state][1][
+ bisect.bisect_right(
+ yy_dfa_states[state][0],
+ ord(block.text[block_pos])
+ )
+ ]
+ block_pos += 1
+ match_len += 1
+ continue
+ # EOF
+ if i == 0:
+ try:
+ return yy_eof_actions[yystart]()
+ except YYTerminate:
+ return 0
+ break
+
+ i = match_len - len(match)
+ if i:
+ assert block is not None
+ match += block.text[block_pos - i:]
+
+ for i in yy_dfa_states[state][2]:
+ yy_group_text = match
+ yy_group_stack = []
+ yy_groups = None
+ yy_groups_by_name = None
+ yy_action = None
+ yytext = None
+ yytext_len = None
+ yy_element_stack = []
+
+ thread = yy_threads0[yy_prefix_slop + i]
+ #print('thread', thread)
+ while thread is not None:
+ pos, ref_data, thread = thread
+ yy_group_stack.append(pos)
+ ref_data()
+
+ yy_element_token = yy_group_element(
+ 0,
+ yytext_len,
+ yy_element_stack.pop(),
+ factory,
+ *args,
+ **kwargs
+ )
+
+ try:
+ return yy_action()
+ except YYReject:
+ pass
+ except YYContinue:
+ break
+ except YYTerminate:
+ return 0
+ else:
+ raise Exception('scanner jammed')
+
+ # append yy_element_token contents onto yy_element_space
+ assert len(yy_element_space.text) == len(yy_element_space) + 1
+ assert len(yy_element_token.text) == len(yy_element_token) + 1
+ yy_element_space.text[-1] += yy_element_token.text[0]
+ yy_element_space.extend(yy_element_token[:])
+ yy_element_space.text.extend(yy_element_token.text[1:])
+
+ # clear yy_element_token for next yytext or EOF action
+ del yy_element_token.text[1:]
+ del yy_element_token[:]
+
+# GENERATE SECTION3