Add forgotten skel_lex_yy.py
authorNick Downing <nick@ndcode.org>
Mon, 18 Feb 2019 10:44:38 +0000 (21:44 +1100)
committerNick Downing <nick@ndcode.org>
Mon, 18 Feb 2019 10:44:38 +0000 (21:44 +1100)
skel_lex_yy.py [new file with mode: 0644]

diff --git a/skel_lex_yy.py b/skel_lex_yy.py
new file mode 100644 (file)
index 0000000..688fc95
--- /dev/null
@@ -0,0 +1,356 @@
+# 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, _class, *args, **kwargs):
+  _element = _class(*args, **kwargs)
+  del _element.text[:]
+  for pos2, pos3, i in reversed(stack):
+    _element.text.append(yy_group_text[pos0:pos2])
+    _element.children.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(_class = 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 = _class(*args, **kwargs)
+  yy_element_token = _class(*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(),
+        _class,
+        *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.children) + 1
+    assert len(yy_element_token.text) == len(yy_element_token.children) + 1
+    yy_element_space.text[-1] += yy_element_token.text[0]
+    yy_element_space.children.extend(yy_element_token.children)
+    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.children[:]
+
+# GENERATE SECTION3