Update to pitree.git commit b3b2036
authorNick Downing <nick@ndcode.org>
Tue, 29 Jan 2019 02:38:25 +0000 (13:38 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 29 Jan 2019 02:49:32 +0000 (13:49 +1100)
Makefile
scan.l
skel/skel_py_element.py
skel_lex_yy.py [new file with mode: 0644]

index 63ca838..408c778 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,8 @@ all: element.py lex_yy.py regex.py t_def.py y_tab.py
 element.py: ../pitree.git/skel/element.py
        cat $< >$@
 
-lex_yy.py: scan.l
-       bootstrap_pilex/pilex.py --element --python $<
+lex_yy.py: scan.l skel_lex_yy.py
+       bootstrap_pilex/pilex.py --element --python --skel skel_lex_yy.py $<
 
 regex.py: regex.t
        ../pitree.git/pitree.py --python -o $@ $<
diff --git a/scan.l b/scan.l
index 1dba096..06c0cc8 100644 (file)
--- a/scan.l
+++ b/scan.l
@@ -1601,30 +1601,29 @@ M4QEND      "]""]"
 # try to use more complex regular expressions to match all in one go:
 
 def markup_flush(n):
-  text = element.get_text(yy_element_token, 0)
-  element.set_text(
-    yy_element_space,
-    len(yy_element_space),
-    element.get_text(yy_element_space, len(yy_element_space)) + text[:n]
-  )
-  element.set_text(yy_element_token, 0, text[n:])
+  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][:n]
+  yy_element_token.text[0] = yy_element_token.text[0][n:]
 
 def markup_yyless(n):
+  assert len(yy_element_space.text) == len(yy_element_space) + 1
+  assert len(yy_element_token.text) == len(yy_element_token) + 1
   yyless(n)
-  element.set_text(
-    yy_element_token,
-    0,
-    element.get_text(yy_element_token, 0)[:n]
-  )
+  yy_element_token.text[0] = yy_element_token.text[0][:n]
 
 def markup_push(factory, *args, **kwargs):
   global 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
   markup_stack.append(yy_element_space)
   yy_element_space = factory(*args, **kwargs)
 
 def markup_pop():
   global 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
   _element = yy_element_space
   yy_element_space = markup_stack.pop()
   yy_element_space.append(_element)
-  #element.set_text(yy_element_space, len(yy_element_space), '')
+  yy_element_space.text.append('')
index f717c35..4ec8675 100644 (file)
@@ -133,11 +133,12 @@ def yy_group_end_element():
 
 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.set_text(_element, len(_element), yy_group_text[pos0:pos2])
+    _element.text.append(yy_group_text[pos0:pos2])
     _element.append(i)
     pos0 = pos3
-  element.set_text(_element, len(_element), yy_group_text[pos0:pos1])
+  _element.text.append(yy_group_text[pos0:pos1])
   return _element
 
 def BEGIN(start):
@@ -342,16 +343,14 @@ def yylex(factory = element.Element, *args, **kwargs):
       raise Exception('scanner jammed')
 
     # append yy_element_token contents onto yy_element_space
-    element.set_text(
-      yy_element_space,
-      len(yy_element_space),
-      element.get_text(yy_element_space, len(yy_element_space)) +
-      element.get_text(yy_element_token, 0)
-    )
-    yy_element_space[len(yy_element_space):] = yy_element_token[:]
+    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
-    element.set_text(yy_element_token, 0, '')
+    del yy_element_token.text[1:]
     del yy_element_token[:]
 
 # GENERATE SECTION3
diff --git a/skel_lex_yy.py b/skel_lex_yy.py
new file mode 100644 (file)
index 0000000..4ec8675
--- /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, 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