Implement %union/<tag>, add https://github.com/gautamkmr/Compiler-Lab- examples
authorNick Downing <downing.nick@gmail.com>
Fri, 20 Jul 2018 12:01:56 +0000 (22:01 +1000)
committerNick Downing <downing.nick@gmail.com>
Fri, 20 Jul 2018 12:01:56 +0000 (22:01 +1000)
28 files changed:
.gitignore
ast.py
bison_lr1dfa.py
bootstrap_pyacc.py
lex-yacc-examples/Makefile [new file with mode: 0644]
lex-yacc-examples/example1.compile [new file with mode: 0644]
lex-yacc-examples/example1.l [new file with mode: 0644]
lex-yacc-examples/example2.compile [new file with mode: 0644]
lex-yacc-examples/example2.l [new file with mode: 0644]
lex-yacc-examples/example3.compile [new file with mode: 0644]
lex-yacc-examples/example3.l [new file with mode: 0644]
lex-yacc-examples/example4.compile [new file with mode: 0644]
lex-yacc-examples/example4.l [new file with mode: 0644]
lex-yacc-examples/example4.y [new file with mode: 0644]
lex-yacc-examples/example5.compile [new file with mode: 0644]
lex-yacc-examples/example5.l [new file with mode: 0644]
lex-yacc-examples/example5.y [new file with mode: 0644]
lex-yacc-examples/example6.compile [new file with mode: 0644]
lex-yacc-examples/example6.l [new file with mode: 0644]
lex-yacc-examples/example6.y [new file with mode: 0644]
lex-yacc-examples/example7.compile [new file with mode: 0644]
lex-yacc-examples/example7.l [new file with mode: 0644]
lex-yacc-examples/example7.y [new file with mode: 0644]
skel/Makefile
skel/skel.y
skel/y.tab.c.patch
skel/y.tab.h.patch [new file with mode: 0644]
tests/Makefile

index ba34001..690c009 100644 (file)
@@ -1,8 +1,16 @@
 __pycache__
+lex-yacc-examples/*.c
+lex-yacc-examples/*.h
+lex-yacc-examples/*.o
+lex-yacc-examples/*.xml
+lex-yacc-examples/example4
+lex-yacc-examples/example7
+skel/y.tab.c
+skel/y.tab.c.orig
+skel/y.tab.h
+skel/y.tab.h.orig
 tests/*.c
 tests/*.o
 tests/*.xml
 tests/cal
 tests/cal2
-skel/y.tab.c
-skel/y.tab.c.orig
diff --git a/ast.py b/ast.py
index 81bd6fa..0bbe302 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -41,7 +41,7 @@ class Item(element.Element):
 class PYACC(element.Element):
   # internal classes
   class Symbol(element.Element):
-    # GENERATE ELEMENT(str name, list(int) character_set) BEGIN
+    # GENERATE ELEMENT(str name, str tag_name, list(int) character_set) BEGIN
     def __init__(
       self,
       tag = 'PYACC_Symbol',
@@ -49,6 +49,7 @@ class PYACC(element.Element):
       text = '',
       children = [],
       name = '',
+      tag_name = '',
       character_set = []
     ):
       element.Element.__init__(
@@ -59,6 +60,7 @@ class PYACC(element.Element):
         children
       )
       self.name = name
+      self.tag_name = tag_name
       self.character_set = (
         [element.deserialize_int(i) for i in character_set.split()]
       if isinstance(character_set, str) else
@@ -67,6 +69,7 @@ class PYACC(element.Element):
     def serialize(self, ref_list):
       element.Element.serialize(self, ref_list)
       self.set('name', element.serialize_str(self.name))
+      self.set('tag_name', element.serialize_str(self.tag_name))
       self.set(
         'character_set',
         ' '.join([element.serialize_int(i) for i in self.character_set])
@@ -74,6 +77,7 @@ class PYACC(element.Element):
     def deserialize(self, ref_list):
       element.Element.deserialize(self, ref_list)
       self.name = element.deserialize_str(self.get('name', ''))
+      self.tag_name = element.deserialize_str(self.get('tag_name', ''))
       self.character_set = [
         element.deserialize_int(i)
         for i in self.get('character_set', '').split()
@@ -84,6 +88,7 @@ class PYACC(element.Element):
         Symbol if factory is None else factory
       )
       result.name = self.name
+      result.tag_name = self.tag_name
       result.character_set = self.character_set
       return result
     def repr_serialize(self, params):
@@ -92,6 +97,10 @@ class PYACC(element.Element):
         params.append(
           'name = {0:s}'.format(repr(self.name))
         )
+      if self.tag_name != '':
+        params.append(
+          'tag_name = {0:s}'.format(repr(self.tag_name))
+        )
       if len(self.character_set):
         params.append(
           'character_set = [{0:s}]'.format(
@@ -113,6 +122,7 @@ class PYACC(element.Element):
       text = '',
       children = [],
       name = '',
+      tag_name = '',
       character_set = [],
       precedence = -1
     ):
@@ -123,6 +133,7 @@ class PYACC(element.Element):
         text,
         children,
         name,
+        tag_name,
         character_set
       )
       self.precedence = (
@@ -164,6 +175,7 @@ class PYACC(element.Element):
       text = '',
       children = [],
       name = '',
+      tag_name = '',
       character_set = []
     ):
       PYACC.Symbol.__init__(
@@ -173,6 +185,7 @@ class PYACC(element.Element):
         text,
         children,
         name,
+        tag_name,
         character_set
       )
     def copy(self, factory = None):
@@ -316,7 +329,8 @@ class PYACC(element.Element):
         production,
         last_action,
         _lr1,
-        symbols
+        symbols,
+        tag_names
       ):
         return last_action
 
@@ -367,12 +381,14 @@ class PYACC(element.Element):
         production,
         last_action,
         _lr1,
-        symbols
+        symbols,
+        tag_names
       ):
         if last_action is not None:
           symbols.append(
             ([], [len(_lr1.productions), len(_lr1.productions) + 1])
           )
+          tag_names.append('')
           _lr1.productions.append(
             (
               # symbols (list of terminal_set, nonterminal_set)
@@ -387,6 +403,12 @@ class PYACC(element.Element):
           if isinstance(i, PYACC.Text.StackLocation):
             i.offset = -production.n_symbols
           elif isinstance(i, PYACC.Text.StackReference):
+            if (
+              len(i.tag_name) == 0 and
+              i.index >= 1 and
+              i.index <= len(tag_names)
+            ):
+              i.tag_name = tag_names[i.index - 1]
             i.offset = -production.n_symbols
         return self[0]
 
@@ -534,8 +556,8 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          -1, # precedence
-          None # tag
+          '', # tag_name
+          -1 # precedence
         )
         assert production.precedence_terminal == -1
         production.precedence_terminal = self[0].terminal
@@ -633,12 +655,14 @@ class PYACC(element.Element):
         production,
         last_action,
         _lr1,
-        symbols
+        symbols,
+        tag_names
       ):
         if last_action is not None:
           symbols.append(
             ([], [len(_lr1.productions), len(_lr1.productions) + 1])
           )
+          tag_names.append('')
           _lr1.productions.append(
             (
               # symbols (list of terminal_set, nonterminal_set)
@@ -649,11 +673,12 @@ class PYACC(element.Element):
               last_action
             )
           )
-        symbols.append(
-          (pyacc.terminals[self.symbol].character_set, [])
-        if self.symbol >= 0 else
-          ([], pyacc.nonterminals[~self.symbol].character_set)
-        )
+        if self.symbol >= 0:
+          symbols.append((pyacc.terminals[self.symbol].character_set, []))
+          tag_names.append(pyacc.terminals[self.symbol].tag_name)
+        else:
+          symbols.append(([], pyacc.nonterminals[~self.symbol].character_set))
+          tag_names.append(pyacc.nonterminals[~self.symbol].tag_name)
         return None
 
     # GENERATE ELEMENT(int lhs_nonterminal, int n_symbols, int last_terminal, int precedence_terminal) BEGIN
@@ -776,16 +801,26 @@ class PYACC(element.Element):
     def add_to_lr1(self, pyacc, _lr1):
       last_action = None
       symbols = []
-      lookaheads = []
+      tag_names = []
       for i in self:
         last_action = i.add_to_symbols(
           pyacc,
           self,
           last_action,
           _lr1,
-          symbols
+          symbols,
+          tag_names
         )
       assert len(symbols) == self.n_symbols
+
+      if last_action is not None:
+        for i in last_action:
+          if (
+            isinstance(i, PYACC.Text.ValueReference) and
+            len(i.tag_name) == 0
+          ):
+            i.tag_name = pyacc.nonterminals[self.lhs_nonterminal].tag_name
+
       _lr1.productions.append(
         (
           # symbols (list of terminal_set, nonterminal_set)
@@ -796,6 +831,7 @@ class PYACC(element.Element):
           last_action
         )
       )
+
       precedence = (
         pyacc.terminals[self.precedence_terminal].precedence
       if self.precedence_terminal != -1 else
@@ -1062,15 +1098,15 @@ class PYACC(element.Element):
         name_to_symbol,
         precedence
       ):
-        tag = None
+        tag_name = ''
         for i in self:
-          tag = i.post_process(
+          tag_name = i.post_process(
             pyacc,
             section,
             character_to_symbol,
             name_to_symbol,
-            precedence,
-            tag
+            tag_name,
+            precedence
           )
 
     class Token(Item):
@@ -1170,6 +1206,15 @@ class PYACC(element.Element):
         self.repr_serialize(params)
         return 'ast.PYACC.Section1Or2.Union({0:s})'.format(', '.join(params))
       # GENERATE END
+      def post_process(
+        self,
+        pyacc,
+        section,
+        character_to_symbol,
+        name_to_symbol
+      ):
+        pyacc.union_name = self[0].get_text()
+        pyacc.union_code = self[1] 
 
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -1638,8 +1683,11 @@ class PYACC(element.Element):
         character_to_symbol,
         name_to_symbol
       ):
-        assert isinstance(self[0], PYACC.Text)
-        pyacc.prologue_text.append(self[0])
+        (
+          pyacc.before_union_code
+        if pyacc.union_code is None else
+          pyacc.after_union_code
+        ).append(self[0])
 
     class Require(Item):
       # GENERATE ELEMENT() BEGIN
@@ -1848,8 +1896,8 @@ class PYACC(element.Element):
           section,
           character_to_symbol,
           name_to_symbol,
-          -1, # precedence
-          None # tag
+          '', # tag_name
+          -1 # precedence
         )
         if pyacc.first_nonterminal == -1:
           pyacc.first_nonterminal = self[0].nonterminal
@@ -1950,8 +1998,8 @@ class PYACC(element.Element):
       section,
       character_to_symbol,
       name_to_symbol,
-      precedence,
-      tag
+      tag_name,
+      precedence
     ):
       raise NotImplementedException
 
@@ -2007,10 +2055,10 @@ class PYACC(element.Element):
       section,
       character_to_symbol,
       name_to_symbol,
-      precedence,
-      tag
+      tag_name,
+      precedence
     ):
-      return self
+      return self[0].get_text()
 
   class TerminalRef(TagOrSymbolRef):
     # GENERATE ELEMENT(int terminal, int user_token) BEGIN
@@ -2077,8 +2125,8 @@ class PYACC(element.Element):
       section,
       character_to_symbol,
       name_to_symbol,
-      precedence,
-      tag
+      tag_name,
+      precedence
     ):
       if isinstance(self[0], PYACC.Char):
         character = ord(self[0][0].get_text())
@@ -2110,10 +2158,13 @@ class PYACC(element.Element):
         pyacc.terminals[self.terminal].character_set = (
           [self.user_token, self.user_token + 1]
         )
+      if len(tag_name):
+        assert len(pyacc.terminals[self.terminal].tag_name) == 0
+        pyacc.terminals[self.terminal].tag_name = tag_name
       if precedence != -1:
         assert pyacc.terminals[self.terminal].precedence == -1
         pyacc.terminals[self.terminal].precedence = precedence
-      return tag
+      return tag_name
 
   class NonterminalRef(TagOrSymbolRef):
     # GENERATE ELEMENT(int nonterminal, int user_token) BEGIN
@@ -2180,8 +2231,8 @@ class PYACC(element.Element):
       section,
       character_to_symbol,
       name_to_symbol,
-      precedence,
-      tag
+      tag_name,
+      precedence
     ):
       if isinstance(self[0], PYACC.ID):
         name = self[0].get_text()
@@ -2197,9 +2248,12 @@ class PYACC(element.Element):
           )
       else:
         assert False
+      if len(tag_name):
+        assert len(pyacc.terminals[self.terminal].tag_name) == 0
+        pyacc.terminals[self.terminal].tag_name = tag_name
       assert self.user_token == -1
       assert precedence == -1
-      return tag
+      return tag_name
 
   class Text(element.Element):
     class Item(element.Element):
@@ -2342,13 +2396,14 @@ class PYACC(element.Element):
       # GENERATE END
 
     class StackReference(Item):
-      # GENERATE ELEMENT(int offset, int index) BEGIN
+      # GENERATE ELEMENT(str tag_name, int offset, int index) BEGIN
       def __init__(
         self,
         tag = 'PYACC_Text_StackReference',
         attrib = {},
         text = '',
         children = [],
+        tag_name = '',
         offset = -1,
         index = -1
       ):
@@ -2359,6 +2414,7 @@ class PYACC(element.Element):
           text,
           children
         )
+        self.tag_name = tag_name
         self.offset = (
           element.deserialize_int(offset)
         if isinstance(offset, str) else
@@ -2371,10 +2427,12 @@ class PYACC(element.Element):
         )
       def serialize(self, ref_list):
         PYACC.Text.Item.serialize(self, ref_list)
+        self.set('tag_name', element.serialize_str(self.tag_name))
         self.set('offset', element.serialize_int(self.offset))
         self.set('index', element.serialize_int(self.index))
       def deserialize(self, ref_list):
         PYACC.Text.Item.deserialize(self, ref_list)
+        self.tag_name = element.deserialize_str(self.get('tag_name', ''))
         self.offset = element.deserialize_int(self.get('offset', '-1'))
         self.index = element.deserialize_int(self.get('index', '-1'))
       def copy(self, factory = None):
@@ -2382,11 +2440,16 @@ class PYACC(element.Element):
           self,
           StackReference if factory is None else factory
         )
+        result.tag_name = self.tag_name
         result.offset = self.offset
         result.index = self.index
         return result
       def repr_serialize(self, params):
         PYACC.Text.Item.repr_serialize(self, params)
+        if self.tag_name != '':
+          params.append(
+            'tag_name = {0:s}'.format(repr(self.tag_name))
+          )
         if self.offset != -1:
           params.append(
             'offset = {0:s}'.format(repr(self.offset))
@@ -2400,8 +2463,17 @@ class PYACC(element.Element):
         self.repr_serialize(params)
         return 'ast.PYACC.Text.StackReference({0:s})'.format(', '.join(params))
       # GENERATE END
-      def get_text(self):   
-        return '(yyvsp[{0:d}])'.format(self.offset + self.index)
+      def get_text(self):
+        return (
+          '(yyvsp[{0:d}].{1:s})'.format(
+            self.offset + self.index,
+            self.tag_name
+          )
+        if len(self.tag_name) else
+          '(yyvsp[{0:d}])'.format(
+            self.offset + self.index,
+          )
+        )
 
     class ValueLocation(Item):
       # GENERATE ELEMENT() BEGIN
@@ -2432,13 +2504,14 @@ class PYACC(element.Element):
       # GENERATE END
 
     class ValueReference(Item):
-      # GENERATE ELEMENT() BEGIN
+      # GENERATE ELEMENT(str tag_name) BEGIN
       def __init__(
         self,
         tag = 'PYACC_Text_ValueReference',
         attrib = {},
         text = '',
-        children = []
+        children = [],
+        tag_name = ''
       ):
         PYACC.Text.Item.__init__(
           self,
@@ -2447,19 +2520,37 @@ class PYACC(element.Element):
           text,
           children
         )
+        self.tag_name = tag_name
+      def serialize(self, ref_list):
+        PYACC.Text.Item.serialize(self, ref_list)
+        self.set('tag_name', element.serialize_str(self.tag_name))
+      def deserialize(self, ref_list):
+        PYACC.Text.Item.deserialize(self, ref_list)
+        self.tag_name = element.deserialize_str(self.get('tag_name', ''))
       def copy(self, factory = None):
         result = PYACC.Text.Item.copy(
           self,
           ValueReference if factory is None else factory
         )
+        result.tag_name = self.tag_name
         return result
+      def repr_serialize(self, params):
+        PYACC.Text.Item.repr_serialize(self, params)
+        if self.tag_name != '':
+          params.append(
+            'tag_name = {0:s}'.format(repr(self.tag_name))
+          )
       def __repr__(self):
         params = []
         self.repr_serialize(params)
         return 'ast.PYACC.Text.ValueReference({0:s})'.format(', '.join(params))
       # GENERATE END
       def get_text(self):
-        return '(yyval)'
+        return (
+          '(yyval.{0:s})'.format(self.tag_name)
+        if len(self.tag_name) else
+          '(yyval)'
+        )
 
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -2588,14 +2679,17 @@ class PYACC(element.Element):
     ):
       pass
 
-  # GENERATE ELEMENT(list(ref) prologue_text, list(ref) terminals, list(ref) nonterminals, int n_productions, list(ref) productions, int first_nonterminal, int start_nonterminal, list(int) associativities) BEGIN
+  # GENERATE ELEMENT(list(ref) before_union_code, str union_name, ref union_code, list(ref) after_union_code, list(ref) terminals, list(ref) nonterminals, int n_productions, list(ref) productions, int first_nonterminal, int start_nonterminal, list(int) associativities) BEGIN
   def __init__(
     self,
     tag = 'PYACC',
     attrib = {},
     text = '',
     children = [],
-    prologue_text = [],
+    before_union_code = [],
+    union_name = '',
+    union_code = None,
+    after_union_code = [],
     terminals = [],
     nonterminals = [],
     n_productions = -1,
@@ -2611,7 +2705,10 @@ class PYACC(element.Element):
       text,
       children
     )
-    self.prologue_text = prologue_text
+    self.before_union_code = before_union_code
+    self.union_name = union_name
+    self.union_code = union_code
+    self.after_union_code = after_union_code
     self.terminals = terminals
     self.nonterminals = nonterminals
     self.n_productions = (
@@ -2638,8 +2735,14 @@ class PYACC(element.Element):
   def serialize(self, ref_list):
     element.Element.serialize(self, ref_list)
     self.set(
-      'prologue_text',
-      ' '.join([element.serialize_ref(i, ref_list) for i in self.prologue_text])
+      'before_union_code',
+      ' '.join([element.serialize_ref(i, ref_list) for i in self.before_union_code])
+    )
+    self.set('union_name', element.serialize_str(self.union_name))
+    self.set('union_code', element.serialize_ref(self.union_code, ref_list))
+    self.set(
+      'after_union_code',
+      ' '.join([element.serialize_ref(i, ref_list) for i in self.after_union_code])
     )
     self.set(
       'terminals',
@@ -2662,9 +2765,15 @@ class PYACC(element.Element):
     )
   def deserialize(self, ref_list):
     element.Element.deserialize(self, ref_list)
-    self.prologue_text = [
+    self.before_union_code = [
       element.deserialize_ref(i, ref_list)
-      for i in self.get('prologue_text', '').split()
+      for i in self.get('before_union_code', '').split()
+    ]
+    self.union_name = element.deserialize_str(self.get('union_name', ''))
+    self.union_code = element.deserialize_ref(self.get('union_code', '-1'), ref_list)
+    self.after_union_code = [
+      element.deserialize_ref(i, ref_list)
+      for i in self.get('after_union_code', '').split()
     ]
     self.terminals = [
       element.deserialize_ref(i, ref_list)
@@ -2690,7 +2799,10 @@ class PYACC(element.Element):
       self,
       PYACC if factory is None else factory
     )
-    result.prologue_text = self.prologue_text
+    result.before_union_code = self.before_union_code
+    result.union_name = self.union_name
+    result.union_code = self.union_code
+    result.after_union_code = self.after_union_code
     result.terminals = self.terminals
     result.nonterminals = self.nonterminals
     result.n_productions = self.n_productions
@@ -2701,10 +2813,24 @@ class PYACC(element.Element):
     return result
   def repr_serialize(self, params):
     element.Element.repr_serialize(self, params)
-    if len(self.prologue_text):
+    if len(self.before_union_code):
+      params.append(
+        'before_union_code = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.before_union_code])
+        )
+      )
+    if self.union_name != '':
+      params.append(
+        'union_name = {0:s}'.format(repr(self.union_name))
+      )
+    if self.union_code != None:
+      params.append(
+        'union_code = {0:s}'.format(repr(self.union_code))
+      )
+    if len(self.after_union_code):
       params.append(
-        'prologue_text = [{0:s}]'.format(
-          ', '.join([repr(i) for i in self.prologue_text])
+        'after_union_code = [{0:s}]'.format(
+          ', '.join([repr(i) for i in self.after_union_code])
         )
       )
     if len(self.terminals):
@@ -2751,7 +2877,10 @@ class PYACC(element.Element):
 
   def post_process(self):
     # variables that will be serialized
-    self.prologue_text = []
+    self.before_union_code = []
+    self.union_name = ''
+    self.union_code = None
+    self.after_union_code = []
     self.precedences = 0
     self.terminals = [
       PYACC.Terminal(name = '$eof', character_set = [0, 1]),
index 6466812..ca437d0 100644 (file)
@@ -256,7 +256,7 @@ class BisonLR1DFA:
     # n_nonterminals == self.goto_pointer.shape[0]
     self.n_terminals = n_terminals
 
-def generate(pyacc, skel_file, out_file):
+def generate(pyacc, skel_file, out_file, defines_file = None):
   lr1dfa = pyacc.to_lr1().to_lalr1()
 
   # generate translate table for terminal symbols
@@ -308,99 +308,116 @@ def generate(pyacc, skel_file, out_file):
     translate_nonterminals
   )
 
-  with open(skel_file, 'r') as fin:
-    with open(out_file, 'w+') as fout:
-      line = fin.readline()
-      while len(line):
-        if line == '/* GENERATE SECTION1FIRST */\n':
-          fout.write(
-            '''/* GENERATE SECTION1FIRST BEGIN */
-{0:s}/* GENERATE SECTION1FIRST END*/
+  def generate(skel_file, out_file):
+    with open(skel_file, 'r') as fin:
+      with open(out_file, 'w+') as fout:
+        line = fin.readline()
+        while len(line):
+          if line == '/* GENERATE SECTION1BEFOREUNION */\n':
+            fout.write(
+              '''/* GENERATE SECTION1BEFOREUNION BEGIN */
+{0:s}/* GENERATE SECTION1BEFOREUNION END */
 '''.format(
-              ''.join([i.get_text() for i in pyacc.prologue_text])
+                ''.join([i.get_text() for i in pyacc.before_union_code])
+              )
             )
-          )
-        elif line == '/* GENERATE TOKENSEQUAL */\n':
-          fout.write(
-            '''/* GENERATE TOKENSEQUAL BEGIN */{0:s}
-/* GENERATE TOKENSEQUAL END*/
+          elif line == '/* GENERATE TOKENSEQUAL */\n':
+            fout.write(
+              '''/* GENERATE TOKENSEQUAL BEGIN */{0:s}
+/* GENERATE TOKENSEQUAL END */
 '''.format(
-              ','.join(
-                [
-                  '\n    {0:s} = {1:d}'.format(i.name, i.character_set[0])
-                  for i in pyacc.terminals[3:]
-                  if len(i.name)
-                ]
+                ','.join(
+                  [
+                    '\n    {0:s} = {1:d}'.format(i.name, i.character_set[0])
+                    for i in pyacc.terminals[3:]
+                    if len(i.name)
+                  ]
+                )
               )
             )
-          )
-        elif line == '/* GENERATE TOKENS */\n':
-          fout.write(
-            '''/* GENERATE TOKENS BEGIN */
-{0:s}/* GENERATE TOKENS END*/
+          elif line == '/* GENERATE TOKENS */\n':
+            fout.write(
+              '''/* GENERATE TOKENS BEGIN */
+{0:s}/* GENERATE TOKENS END */
 '''.format(
-              ''.join(
-                [
-                  '#define {0:s} {1:d}\n'.format(i.name, i.character_set[0])
-                  for i in pyacc.terminals[3:]
-                  if len(i.name)
-                ]
+                ''.join(
+                  [
+                    '#define {0:s} {1:d}\n'.format(i.name, i.character_set[0])
+                    for i in pyacc.terminals[3:]
+                    if len(i.name)
+                  ]
+                )
               )
             )
-          )
-        elif line == '/* GENERATE SECTION1SECOND */\n':
-          fout.write(
-            '''/* GENERATE SECTION1SECOND BEGIN */
-{0:s}/* GENERATE SECTION1SECOND END*/
+          elif line == '/* GENERATE UNION */\n':
+            fout.write(
+                '''/* GENERATE UNION BEGIN */
+typedef int YYSTYPE;
+/* GENERATE UNION END */
+'''
+              if pyacc.union_code is None else
+                '''/* GENERATE UNION BEGIN */
+union YYSTYPE
+{0:s};
+typedef union YYSTYPE YYSTYPE;
+/* GENERATE UNION END */
 '''.format(
-              '' # fix this later
+                  pyacc.union_code.get_text()
+                )
+            )
+          elif line == '/* GENERATE SECTION1AFTERUNION */\n':
+            fout.write(
+              '''/* GENERATE SECTION1AFTERUNION BEGIN */
+{0:s}/* GENERATE SECTION1AFTERUNION END */
+'''.format(
+                ''.join([i.get_text() for i in pyacc.after_union_code])
+              )
+            )
+          elif line == '/* GENERATE TABLES */\n':
+            # yyrline (source line where rule is defined) not implemented yet
+            yyrline = numpy.zeros(
+              (bison_lr1dfa.rule_data.shape[0],),
+              numpy.int16
             )
-          )
-        elif line == '/* GENERATE TABLES */\n':
-          # yyrline (source line where rule is defined) not implemented yet
-          yyrline = numpy.zeros(
-            (bison_lr1dfa.rule_data.shape[0],),
-            numpy.int16
-          )
 
-          # yytname (textual terminal/nonterminal name) wraps 70 columns
-          x = 70
-          yytname_lines = []
-          for i in (
-            [
-              (
-                '"{0:s}"'.format(i.name)
-              if len(i.name) else
-                '"\'{0:s}\'"'.format(
-                  chr(i.character_set[0])
-                if i.character_set[0] >= 0x20 else
-                  '\\\\x{0:02x}'.format(i.character_set[0])
+            # yytname (textual terminal/nonterminal name) wraps 70 columns
+            x = 70
+            yytname_lines = []
+            for i in (
+              [
+                (
+                  '"{0:s}"'.format(i.name)
+                if len(i.name) else
+                  '"\'{0:s}\'"'.format(
+                    chr(i.character_set[0])
+                  if i.character_set[0] >= 0x20 else
+                    '\\\\x{0:02x}'.format(i.character_set[0])
+                  )
                 )
-              )
-              for i in pyacc.terminals
-            ] +
-            ['"{0:s}"'.format(i.name) for i in pyacc.nonterminals] +
-            ['"$@{0:d}"'.format(i) for i in range(n_midrule_actions)] +
-            ['YY_NULLPTR']
-          ):
-            if x + len(i) >= 70:
-              yytname_lines.append([])
-              x = 0
-            yytname_lines[-1].append(i)
-            x += len(i) + 2
-
-          # yytoknum is the approximate reverse of bison_lr1dfa.translate,
-          # do in reverse order so later duplicate entries get overwritten
-          yytoknum = numpy.zeros((bison_lr1dfa.n_terminals,), numpy.int16)
-          yytoknum[bison_lr1dfa.translate[::-1]] = numpy.arange(
-            bison_lr1dfa.translate.shape[0] - 1,
-            -1,
-            -1,
-            numpy.int16
-          )
+                for i in pyacc.terminals
+              ] +
+              ['"{0:s}"'.format(i.name) for i in pyacc.nonterminals] +
+              ['"$@{0:d}"'.format(i) for i in range(n_midrule_actions)] +
+              ['YY_NULLPTR']
+            ):
+              if x + len(i) >= 70:
+                yytname_lines.append([])
+                x = 0
+              yytname_lines[-1].append(i)
+              x += len(i) + 2
+
+            # yytoknum is the approximate reverse of bison_lr1dfa.translate,
+            # do in reverse order so later duplicate entries get overwritten
+            yytoknum = numpy.zeros((bison_lr1dfa.n_terminals,), numpy.int16)
+            yytoknum[bison_lr1dfa.translate[::-1]] = numpy.arange(
+              bison_lr1dfa.translate.shape[0] - 1,
+              -1,
+              -1,
+              numpy.int16
+            )
 
-          fout.write(
-            '''/* GENERATE TABLES BEGIN */
+            fout.write(
+              '''/* GENERATE TABLES BEGIN */
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL {0:d}
 /* YYLAST -- Last index in YYTABLE.  */
@@ -513,234 +530,242 @@ static const yytype_int16 yyr2[] =
 }};
 /* GENERATE TABLES END */
 '''.format(
-              # YYFINAL
-              bison_lr1dfa.action_pointer.shape[0],
-              # YYLAST
-              bison_lr1dfa.entry_data.shape[0] - 1,
-              # YYNTOKENS
-              bison_lr1dfa.n_terminals,
-              # YYNNTS
-              bison_lr1dfa.goto_pointer.shape[0],
-              # YYNRULES
-              bison_lr1dfa.rule_data.shape[0],
-              # YYNSTATES
-              bison_lr1dfa.action_pointer.shape[0],
-              # YYMAXUTOK
-              bison_lr1dfa.translate.shape[0] - 1,
-              # yytranslate
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.translate[i:i + 10]
-                      ]
+                # YYFINAL
+                bison_lr1dfa.action_pointer.shape[0],
+                # YYLAST
+                bison_lr1dfa.entry_data.shape[0] - 1,
+                # YYNTOKENS
+                bison_lr1dfa.n_terminals,
+                # YYNNTS
+                bison_lr1dfa.goto_pointer.shape[0],
+                # YYNRULES
+                bison_lr1dfa.rule_data.shape[0],
+                # YYNSTATES
+                bison_lr1dfa.action_pointer.shape[0],
+                # YYMAXUTOK
+                bison_lr1dfa.translate.shape[0] - 1,
+                # yytranslate
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.translate[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.translate.shape[0], 10)
-                ]
-              ),
-              # yyrline
-              ','.join(
-                [
-                  '\n{0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in yyrline[i:i + 10]
-                      ]
+                    for i in range(0, bison_lr1dfa.translate.shape[0], 10)
+                  ]
+                ),
+                # yyrline
+                ','.join(
+                  [
+                    '\n{0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in yyrline[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, yyrline.shape[0], 10)
-                ]
-              ),
-              # yytname
-              ','.join(
-                ['\n  {0:s}'.format(', '.join(i)) for i in yytname_lines]
-              ),
-              # yytoknum
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in yytoknum[i:i + 10]
-                      ]
+                    for i in range(0, yyrline.shape[0], 10)
+                  ]
+                ),
+                # yytname
+                ','.join(
+                  ['\n  {0:s}'.format(', '.join(i)) for i in yytname_lines]
+                ),
+                # yytoknum
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in yytoknum[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, yytoknum.shape[0], 10)
-                ]
-              ),
-              # YYPACT_NINF
-              -bison_lr1dfa.entry_base,
-              # yypact_value_is_default
-              -bison_lr1dfa.entry_base,
-              # yypact
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.action_pointer[i:i + 10]
-                      ]
+                    for i in range(0, yytoknum.shape[0], 10)
+                  ]
+                ),
+                # YYPACT_NINF
+                -bison_lr1dfa.entry_base,
+                # yypact_value_is_default
+                -bison_lr1dfa.entry_base,
+                # yypact
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.action_pointer[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.action_pointer.shape[0], 10)
-                ]
-              ),
-              # yydefact
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.default_action[i:i + 10]
-                      ]
+                    for i in range(0, bison_lr1dfa.action_pointer.shape[0], 10)
+                  ]
+                ),
+                # yydefact
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.default_action[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.default_action.shape[0], 10)
-                ]
-              ),
-              # yypgoto
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.goto_pointer[i:i + 10]
-                      ]
+                    for i in range(0, bison_lr1dfa.default_action.shape[0], 10)
+                  ]
+                ),
+                # yypgoto
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.goto_pointer[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.goto_pointer.shape[0], 10)
-                ]
-              ),
-              # yydefgoto
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.default_goto[i:i + 10]
-                      ]
+                    for i in range(0, bison_lr1dfa.goto_pointer.shape[0], 10)
+                  ]
+                ),
+                # yydefgoto
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.default_goto[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.default_goto.shape[0], 10)
-                ]
-              ),
-              # yytable
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.entry_data[i:i + 10, 0]
-                      ]
+                    for i in range(0, bison_lr1dfa.default_goto.shape[0], 10)
+                  ]
+                ),
+                # yytable
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.entry_data[i:i + 10, 0]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.entry_data.shape[0], 10)
-                ]
-              ),
-              # yycheck
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.entry_data[i:i + 10, 1]
-                      ]
+                    for i in range(0, bison_lr1dfa.entry_data.shape[0], 10)
+                  ]
+                ),
+                # yycheck
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.entry_data[i:i + 10, 1]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.entry_data.shape[0], 10)
-                ]
-              ),
-              # yystos
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.accessing_symbols[i:i + 10]
-                      ]
+                    for i in range(0, bison_lr1dfa.entry_data.shape[0], 10)
+                  ]
+                ),
+                # yystos
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.accessing_symbols[i:i + 10]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.accessing_symbols.shape[0], 10)
-                ]
-              ),
-              # yyr1
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.rule_data[i:i + 10, 0]
-                      ]
+                    for i in range(0, bison_lr1dfa.accessing_symbols.shape[0], 10)
+                  ]
+                ),
+                # yyr1
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.rule_data[i:i + 10, 0]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.rule_data.shape[0], 10)
-                ]
-              ),
-              # yyr2
-              ','.join(
-                [
-                  '\n  {0:s}'.format(
-                    ','.join(
-                      [
-                        '{0:6d}'.format(j)
-                        for j in bison_lr1dfa.rule_data[i:i + 10, 1]
-                      ]
+                    for i in range(0, bison_lr1dfa.rule_data.shape[0], 10)
+                  ]
+                ),
+                # yyr2
+                ','.join(
+                  [
+                    '\n  {0:s}'.format(
+                      ','.join(
+                        [
+                          '{0:6d}'.format(j)
+                          for j in bison_lr1dfa.rule_data[i:i + 10, 1]
+                        ]
+                      )
                     )
-                  )
-                  for i in range(0, bison_lr1dfa.rule_data.shape[0], 10)
-                ]
+                    for i in range(0, bison_lr1dfa.rule_data.shape[0], 10)
+                  ]
+                )
               )
             )
-          )
-        elif line == '/* GENERATE SECTION2INITIAL */\n':
-          fout.write(
-            '''/* GENERATE SECTION2INITIAL BEGIN */
+          elif line == '/* GENERATE SECTION2INITIAL */\n':
+            fout.write(
+              '''/* GENERATE SECTION2INITIAL BEGIN */
 {0:s}/* GENERATE SECTION2INITIAL END */
 '''.format(
-              '' #.join([i.get_text() for i in pyacc[1].code_blocks])
+                '' #.join([i.get_text() for i in pyacc[1].code_blocks])
+              )
             )
-          )
-        elif line == '/* GENERATE SECTION2 */\n':
-          fout.write(
-            '''/* GENERATE SECTION2 BEGIN */
+          elif line == '/* GENERATE SECTION2 */\n':
+            fout.write(
+              '''/* GENERATE SECTION2 BEGIN */
 {0:s}/* GENERATE SECTION2 END */
 '''.format(
-              '\n'.join(
-                [
-                  '''  case {0:d}:
+                '\n'.join(
+                  [
+                    '''  case {0:d}:
     {1:s}
     break;
 '''.format(
-                    i,
-                    lr1dfa.productions[i][1].get_text()
-                  )
-                  for i in range(len(lr1dfa.productions))
-                  if lr1dfa.productions[i][1] is not None
-                ]
+                      i,
+                      lr1dfa.productions[i][1].get_text()
+                    )
+                    for i in range(len(lr1dfa.productions))
+                    if lr1dfa.productions[i][1] is not None
+                  ]
+                )
               )
             )
-          )
-        elif line == '/* GENERATE SECTION3 */\n':
-          fout.write(
-            '''/* GENERATE SECTION3 BEGIN */
+          elif line == '/* GENERATE SECTION3 */\n':
+            fout.write(
+              '''/* GENERATE SECTION3 BEGIN */
 {0:s}/*GENERATE SECTION3 END */
 '''.format(
-              '' if len(pyacc) < 3 else pyacc[2].get_text()
+                '' if len(pyacc) < 3 else pyacc[2].get_text()
+              )
             )
-          )
-        else:
-          fout.write(line)
-        line = fin.readline()
+          else:
+            fout.write(line)
+          line = fin.readline()
+  generate(skel_file, out_file)
+  if defines_file is not None:
+    generate(
+      '{0:s}.h'.format(
+        skel_file[:-2] if skel_file[-2:] == '.c' else skel_file
+      ),
+      defines_file
+    )
index 7aa87b2..5094f4b 100755 (executable)
@@ -10,15 +10,24 @@ import xml.etree.ElementTree
 
 home_dir = os.path.dirname(sys.argv[0])
 try:
-  opts, args = getopt.getopt(sys.argv[1:], 'o:S:', ['outfile=', 'skel='])
+  opts, args = getopt.getopt(
+    sys.argv[1:],
+    'do:S:',
+    ['defines', 'defines=', 'outfile=', 'skel=']
+  )
 except getopt.GetoptError as err:
-  sys.stderr.write(str(err))
+  sys.stderr.write(str(err) + '\n')
   sys.exit(1)
 
+defines_file = None
 out_file = 'y.tab.c'
 skel_file = os.path.join(home_dir, 'skel/y.tab.c')
 for opt, arg in opts:
-  if opt == '-o' or opt == '--outfile':
+  if opt == '-d':
+    defines_file = 'y.tab.h'
+  elif opt == '--defines':
+    defines_file = arg
+  elif opt == '-o' or opt == '--outfile':
     out_file = arg
   elif opt == '-S' or opt == '--skel':
     skel_file = arg
@@ -40,4 +49,4 @@ with open(in_file) as fin:
 pyacc.post_process()
 #element.serialize(pyacc, 'b.xml', 'utf-8')
 #pyacc = element.deserialize('b.xml', ast.factory, 'utf-8')
-bison_lr1dfa.generate(pyacc, skel_file, out_file)
+bison_lr1dfa.generate(pyacc, skel_file, out_file, defines_file)
diff --git a/lex-yacc-examples/Makefile b/lex-yacc-examples/Makefile
new file mode 100644 (file)
index 0000000..b277eb3
--- /dev/null
@@ -0,0 +1,41 @@
+all: example4 example7
+
+# example4 program
+example4: example4.tab.o example4.yy.o
+       ${CC} -o $@ $^
+
+example4.tab.o: example4.tab.c
+
+example4.tab.c: example4.y
+       ../../bootstrap_bison.git/src/bison -y -o /dev/null $< 2>$<.xml
+       ../bootstrap_pyacc.py -d $<.xml
+       mv y.tab.h example4.tab.h
+       mv y.tab.c $@
+
+example4.yy.o: example4.yy.c
+
+example4.yy.c: example4.l
+       ../../bootstrap_flex.git/src/flex $< 2>$<.xml
+       mv lex.yy.c $@
+
+# example7 program
+example7: example7.tab.o example7.yy.o
+       ${CC} -o $@ $^
+
+example7.tab.o: example7.tab.c
+
+example7.tab.c: example7.y
+       ../../bootstrap_bison.git/src/bison -y -o /dev/null $< 2>$<.xml
+       ../bootstrap_pyacc.py -d $<.xml
+       mv y.tab.h example7.tab.h
+       mv y.tab.c $@
+
+example7.yy.o: example7.yy.c
+
+example7.yy.c: example7.l
+       ../../bootstrap_flex.git/src/flex $< 2>$<.xml
+       mv lex.yy.c $@
+
+# other
+clean:
+       rm -f *.c *.o *.xml example4 example7
diff --git a/lex-yacc-examples/example1.compile b/lex-yacc-examples/example1.compile
new file mode 100644 (file)
index 0000000..a86d44b
--- /dev/null
@@ -0,0 +1,2 @@
+lex example1.l
+cc lex.yy.c -o example1 -ll
diff --git a/lex-yacc-examples/example1.l b/lex-yacc-examples/example1.l
new file mode 100644 (file)
index 0000000..234f412
--- /dev/null
@@ -0,0 +1,8 @@
+%{
+#include <stdio.h>
+%}
+
+%%
+stop   printf("Stop command received\n");
+start  printf("Start command received\n");
+%%
diff --git a/lex-yacc-examples/example2.compile b/lex-yacc-examples/example2.compile
new file mode 100644 (file)
index 0000000..c1fb80c
--- /dev/null
@@ -0,0 +1,2 @@
+lex example2.l
+cc lex.yy.c -o example2 -ll
diff --git a/lex-yacc-examples/example2.l b/lex-yacc-examples/example2.l
new file mode 100644 (file)
index 0000000..2528382
--- /dev/null
@@ -0,0 +1,8 @@
+%{
+#include <stdio.h>
+%}
+
+%%
+[0123456789]+          printf("NUMBER\n");
+[a-zA-Z][a-zA-Z0-9]*   printf("WORD\n");
+%%
diff --git a/lex-yacc-examples/example3.compile b/lex-yacc-examples/example3.compile
new file mode 100644 (file)
index 0000000..ff734a2
--- /dev/null
@@ -0,0 +1,2 @@
+lex example3.l
+cc lex.yy.c -o example3 -ll
diff --git a/lex-yacc-examples/example3.l b/lex-yacc-examples/example3.l
new file mode 100644 (file)
index 0000000..f2784fe
--- /dev/null
@@ -0,0 +1,14 @@
+%{
+#include <stdio.h>
+%}
+
+%%
+[a-zA-Z][a-zA-Z0-9]*    printf("WORD ");
+[a-zA-Z0-9\/.-]+        printf("FILENAME ");
+\"                      printf("QUOTE ");
+\{                      printf("OBRACE ");
+\}                      printf("EBRACE ");
+;                       printf("SEMICOLON ");
+\n                      printf("\n");
+[ \t]+                  /* ignore whitespace */;
+%%
diff --git a/lex-yacc-examples/example4.compile b/lex-yacc-examples/example4.compile
new file mode 100644 (file)
index 0000000..304d3ae
--- /dev/null
@@ -0,0 +1,3 @@
+lex example4.l
+yacc -d example4.y
+cc lex.yy.c y.tab.c -o example4 
diff --git a/lex-yacc-examples/example4.l b/lex-yacc-examples/example4.l
new file mode 100644 (file)
index 0000000..d445ab8
--- /dev/null
@@ -0,0 +1,13 @@
+%{
+#include <stdio.h>
+#include "example4.tab.h" /*"y.tab.h"*/
+%}
+%%
+[0-9]+                  return NUMBER;
+heat                    return TOKHEAT;
+on|off                  return STATE;
+target                  return TOKTARGET;
+temperature             return TOKTEMPERATURE;
+\n                      /* ignore end of line */;
+[ \t]+                  /* ignore whitespace */;
+%%
diff --git a/lex-yacc-examples/example4.y b/lex-yacc-examples/example4.y
new file mode 100644 (file)
index 0000000..f4b1a49
--- /dev/null
@@ -0,0 +1,50 @@
+%{
+#include <stdio.h>
+#include <string.h>
+
+void yyerror(const char *str)
+{
+       fprintf(stderr,"error: %s\n",str);
+}
+
+int yywrap()
+{
+       return 1;
+}
+
+main()
+{
+       yyparse();
+}
+
+%}
+
+%token NUMBER TOKHEAT STATE TOKTARGET TOKTEMPERATURE
+
+%%
+
+commands: /* empty */
+       | commands command
+       ;
+
+
+command:
+       heat_switch
+       |
+       target_set
+       ;
+
+heat_switch:
+       TOKHEAT STATE 
+       {
+               printf("\tHeat turned on or off\n");
+       }
+       ;
+
+target_set:
+       TOKTARGET TOKTEMPERATURE NUMBER
+       {
+               printf("\tTemperature set\n");
+       }
+       ;
+
diff --git a/lex-yacc-examples/example5.compile b/lex-yacc-examples/example5.compile
new file mode 100644 (file)
index 0000000..4d8edb1
--- /dev/null
@@ -0,0 +1,3 @@
+lex example5.l
+yacc -d example5.y
+cc lex.yy.c y.tab.c -o example5 
diff --git a/lex-yacc-examples/example5.l b/lex-yacc-examples/example5.l
new file mode 100644 (file)
index 0000000..59b942d
--- /dev/null
@@ -0,0 +1,13 @@
+%{
+#include <stdio.h>
+#include "example5.tab.h" /*"y.tab.h"*/
+%}
+%%
+[0-9]+                  yylval=atoi(yytext); return NUMBER;
+heat                    return TOKHEAT;
+on|off                  yylval=!strcmp(yytext,"on"); return STATE;
+target                  return TOKTARGET;
+temperature             return TOKTEMPERATURE;
+\n                      /* ignore end of line */;
+[ \t]+                  /* ignore whitespace */;
+%%
diff --git a/lex-yacc-examples/example5.y b/lex-yacc-examples/example5.y
new file mode 100644 (file)
index 0000000..65ba2f7
--- /dev/null
@@ -0,0 +1,53 @@
+%{
+#include <stdio.h>
+#include <string.h>
+
+void yyerror(const char *str)
+{
+       fprintf(stderr,"error: %s\n",str);
+}
+
+int yywrap()
+{
+       return 1;
+}
+
+main()
+{
+       yyparse();
+}
+
+%}
+
+%token NUMBER TOKHEAT STATE TOKTARGET TOKTEMPERATURE
+
+%%
+
+commands:
+       | commands command
+       ;
+
+
+command:
+       heat_switch
+       |
+       target_set
+       ;
+
+heat_switch:
+       TOKHEAT STATE 
+       {
+               if($2)
+                       printf("\tHeat turned on\n");
+               else
+                       printf("\tHeat turned off\n");
+       }
+       ;
+
+target_set:
+       TOKTARGET TOKTEMPERATURE NUMBER
+       {
+               printf("\tTemperature set to %d\n",$3);
+       }
+       ;
+
diff --git a/lex-yacc-examples/example6.compile b/lex-yacc-examples/example6.compile
new file mode 100644 (file)
index 0000000..d4601d4
--- /dev/null
@@ -0,0 +1,3 @@
+lex example6.l
+yacc --verbose --debug -d example6.y
+cc lex.yy.c y.tab.c -o example6 
diff --git a/lex-yacc-examples/example6.l b/lex-yacc-examples/example6.l
new file mode 100644 (file)
index 0000000..4bd41e6
--- /dev/null
@@ -0,0 +1,18 @@
+%{
+#include <stdio.h>
+#include "example6.tab.h" /*"y.tab.h"*/
+%}
+
+%%
+
+zone                   return ZONETOK;
+file                   return FILETOK;
+[a-zA-Z][a-zA-Z0-9]*    yylval=strdup(yytext); return WORD;
+[a-zA-Z0-9\/.-]+        yylval=strdup(yytext); return FILENAME;
+\"                      return QUOTE;
+\{                      return OBRACE;
+\}                      return EBRACE;
+;                       return SEMICOLON;
+\n                      /* ignore EOL */;
+[ \t]+                  /* ignore whitespace */;
+%%
diff --git a/lex-yacc-examples/example6.y b/lex-yacc-examples/example6.y
new file mode 100644 (file)
index 0000000..aa9b67c
--- /dev/null
@@ -0,0 +1,79 @@
+%{
+#include <stdio.h>
+#include <string.h>
+
+#define YYSTYPE char *
+
+int yydebug=0;
+
+void yyerror(const char *str)
+{
+       fprintf(stderr,"error: %s\n",str);
+}
+
+int yywrap()
+{
+       return 1;
+}
+
+main()
+{
+       yyparse();
+}
+
+%}
+
+%token WORD FILENAME QUOTE OBRACE EBRACE SEMICOLON ZONETOK FILETOK
+
+%%
+
+commands:
+       |        
+       commands command SEMICOLON
+       ;
+
+
+command:
+       zone_set 
+       ;
+
+zone_set:
+       ZONETOK quotedname zonecontent
+       {
+               printf("Complete zone for '%s' found\n",$2);
+       }
+       ;
+
+zonecontent:
+       OBRACE zonestatements EBRACE 
+
+quotedname:
+       QUOTE FILENAME QUOTE
+       {
+               $$=$2;
+       }
+       ;
+
+zonestatements:
+       |
+       zonestatements zonestatement SEMICOLON
+       ;
+
+zonestatement:
+       statements
+       |
+       FILETOK quotedname 
+       {
+               printf("A zonefile name '%s' was encountered\n", $2);
+       }
+       ;
+
+block: 
+       OBRACE zonestatements EBRACE SEMICOLON
+       ;
+
+statements:
+       | statements statement
+       ;
+
+statement: WORD | block | quotedname
diff --git a/lex-yacc-examples/example7.compile b/lex-yacc-examples/example7.compile
new file mode 100644 (file)
index 0000000..b2b9129
--- /dev/null
@@ -0,0 +1,3 @@
+lex example7.l
+yacc -d example7.y
+cc lex.yy.c y.tab.c -o example7 
diff --git a/lex-yacc-examples/example7.l b/lex-yacc-examples/example7.l
new file mode 100644 (file)
index 0000000..f4bc9ae
--- /dev/null
@@ -0,0 +1,16 @@
+%{
+#include <stdio.h>
+#include <string.h>
+#include "example7.tab.h" /*"y.tab.h"*/
+%}
+%%
+[0-9]+                  yylval.number=atoi(yytext); return NUMBER;
+heater                 return TOKHEATER;
+heat                    return TOKHEAT;
+on|off                  yylval.number=!strcmp(yytext,"on"); return STATE;
+target                  return TOKTARGET;
+temperature             return TOKTEMPERATURE;
+[a-z0-9]+              yylval.string=strdup(yytext);return WORD;
+\n                      /* ignore end of line */;
+[ \t]+                  /* ignore whitespace */;
+%%
diff --git a/lex-yacc-examples/example7.y b/lex-yacc-examples/example7.y
new file mode 100644 (file)
index 0000000..bf8566f
--- /dev/null
@@ -0,0 +1,69 @@
+%{
+#include <stdio.h>
+#include <string.h>
+
+void yyerror(const char *str)
+{
+       fprintf(stderr,"error: %s\n",str);
+}
+
+int yywrap()
+{
+       return 1;
+}
+
+main()
+{
+       yyparse();
+}
+
+char *heater="default";
+
+%}
+
+%token TOKHEATER TOKHEAT TOKTARGET TOKTEMPERATURE
+
+%union 
+{
+       int number;
+       char *string;
+}
+
+%token <number> STATE
+%token <number> NUMBER
+%token <string> WORD
+
+%%
+
+commands:
+       | commands command
+       ;
+
+
+command:
+       heat_switch | target_set | heater_select
+
+heat_switch:
+       TOKHEAT STATE 
+       {
+               if($2)
+                       printf("\tHeater '%s' turned on\n", heater);
+               else
+                       printf("\tHeat '%s' turned off\n", heater);
+       }
+       ;
+
+target_set:
+       TOKTARGET TOKTEMPERATURE NUMBER
+       {
+               printf("\tHeater '%s' temperature set to %d\n",heater, $3);
+       }
+       ;
+
+heater_select:
+       TOKHEATER WORD
+       {
+               printf("\tSelected heater '%s'\n",$2);
+               heater=$2;
+       }
+       ;
\ No newline at end of file
index c61c7fd..4ce396a 100644 (file)
@@ -1,4 +1,6 @@
 y.tab.c: skel.y
-       ../../bootstrap_bison.git/src/bison -y $<
+       ../../bootstrap_bison.git/src/bison -dy $<
        cp $@ $@.orig
        patch $@ <$@.patch
+       cp y.tab.h y.tab.h.orig
+       patch y.tab.h <y.tab.h.patch
index ba84706..24b6c6a 100644 (file)
@@ -1,4 +1,5 @@
 %token TOKEN
 %start start
+%union { /* something */ }
 %%
 start: { /* do something */ } | start TOKEN { /* do something else */ };
index 97c971d..b475840 100644 (file)
@@ -1,15 +1,15 @@
---- y.tab.c.orig       2018-07-06 07:51:34.462479398 +1000
-+++ y.tab.c    2018-07-06 09:03:46.066520012 +1000
+--- y.tab.c.orig       2018-07-20 21:54:15.781339387 +1000
++++ y.tab.c    2018-07-20 21:55:37.481335930 +1000
 @@ -63,7 +63,7 @@
  
  /* Copy the first part of user declarations.  */
  
 -#line 67 "y.tab.c" /* yacc.c:339  */
-+/* GENERATE SECTION1FIRST */
++/* GENERATE SECTION1BEFOREUNION */
  
  # ifndef YY_NULLPTR
  #  if defined __cplusplus && 201103L <= __cplusplus
-@@ -95,11 +95,11 @@
+@@ -98,24 +98,15 @@
  # define YYTOKENTYPE
    enum yytokentype
    {
  
  /* Value type.  */
  #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-@@ -117,7 +117,7 @@
+-
+-union YYSTYPE
+-{
+-#line 3 "skel.y" /* yacc.c:355  */
+- /* something */ 
+-
+-#line 116 "y.tab.c" /* yacc.c:355  */
+-};
+-
+-typedef union YYSTYPE YYSTYPE;
++/* GENERATE UNION */
+ # define YYSTYPE_IS_TRIVIAL 1
+ # define YYSTYPE_IS_DECLARED 1
+ #endif
+@@ -129,7 +120,7 @@
  
  /* Copy the second part of user declarations.  */
  
--#line 121 "y.tab.c" /* yacc.c:358  */
-+/* GENERATE SECTION1SECOND */
+-#line 133 "y.tab.c" /* yacc.c:358  */
++/* GENERATE SECTION1AFTERUNION */
  
  #ifdef short
  # undef short
-@@ -356,156 +356,8 @@
+@@ -368,155 +359,7 @@
  # endif
  #endif /* !YYCOPY_NEEDED */
  
 -  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 -static const yytype_uint8 yyrline[] =
 -{
--       0,     4,     4,     4
+-       0,     5,     5,     5
 -};
 -#endif
 -
 -       0,     2,     0,     2
 -};
 -
--
 +/* GENERATE TABLES */
-+ 
  #define yyerrok         (yyerrstatus = 0)
  #define yyclearin       (yychar = YYEMPTY)
- #define YYEMPTY         (-2)
-@@ -1179,20 +1031,8 @@
+@@ -1191,20 +1034,8 @@
    YY_REDUCE_PRINT (yyn);
    switch (yyn)
      {
 -        case 2:
--#line 4 "skel.y" /* yacc.c:1648  */
+-#line 5 "skel.y" /* yacc.c:1648  */
 -    { /* do something */ }
--#line 1186 "y.tab.c" /* yacc.c:1648  */
+-#line 1198 "y.tab.c" /* yacc.c:1648  */
 -    break;
 -
 -  case 3:
--#line 4 "skel.y" /* yacc.c:1648  */
+-#line 5 "skel.y" /* yacc.c:1648  */
 -    { /* do something else */ }
--#line 1192 "y.tab.c" /* yacc.c:1648  */
+-#line 1204 "y.tab.c" /* yacc.c:1648  */
 -    break;
 -
 +/* GENERATE SECTION2 */
  
--#line 1196 "y.tab.c" /* yacc.c:1648  */
+-#line 1208 "y.tab.c" /* yacc.c:1648  */
        default: break;
      }
    /* User semantic actions sometimes alter yychar, and that requires
-@@ -1420,3 +1260,5 @@
+@@ -1432,3 +1263,5 @@
  #endif
    return yyresult;
  }
diff --git a/skel/y.tab.h.patch b/skel/y.tab.h.patch
new file mode 100644 (file)
index 0000000..21c8d73
--- /dev/null
@@ -0,0 +1,29 @@
+--- y.tab.h.orig       2018-07-20 21:53:34.541341132 +1000
++++ y.tab.h    2018-07-20 21:54:00.765340023 +1000
+@@ -45,7 +45,7 @@
+ # define YYTOKENTYPE
+   enum yytokentype
+   {
+-    TOKEN = 258
++/* GENERATE TOKENSEQUAL */
+   };
+ #endif
+ /* Tokens.  */
+@@ -53,16 +53,7 @@
+ /* Value type.  */
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+-
+-union YYSTYPE
+-{
+-#line 3 "skel.y" /* yacc.c:1910  */
+- /* something */ 
+-
+-#line 63 "y.tab.h" /* yacc.c:1910  */
+-};
+-
+-typedef union YYSTYPE YYSTYPE;
++/* GENERATE UNION */
+ # define YYSTYPE_IS_TRIVIAL 1
+ # define YYSTYPE_IS_DECLARED 1
+ #endif
index 61a1c88..8b8d23d 100644 (file)
@@ -13,7 +13,7 @@ y.tab.c: cal.y
 lex.yy.c: cal.l
        ../../bootstrap_flex.git/src/flex $< 2>$<.xml
 
-# cal2 progarm
+# cal2 program
 cal2: y.tab2.o
        ${CC} -o $@ $<