openflow_input: changed syntax for openflow input parsing of enums
diff --git a/loxi_front_end/frontend.py b/loxi_front_end/frontend.py
index c093a95..f4dece5 100644
--- a/loxi_front_end/frontend.py
+++ b/loxi_front_end/frontend.py
@@ -25,6 +25,8 @@
 # EPL for the specific language governing permissions and limitations
 # under the EPL.
 
+from generic_utils import find
+from collections import namedtuple
 import copy
 import of_g
 import loxi_front_end.type_maps as type_maps
@@ -33,25 +35,35 @@
 class InputError(Exception):
     pass
 
-def create_member(m_ast):
+
+FrontendCtx = namedtuple("FrontendCtx", ("used_enums"))
+
+def get_type(t_ast, ctx):
+    if t_ast[0] == "enum":
+        ctx.used_enums.add(t_ast[1])
+
+    return t_ast[1]
+
+def create_member(m_ast, ctx):
     if m_ast[0] == 'pad':
         return OFPadMember(length=m_ast[1])
     elif m_ast[0] == 'type':
-        return OFTypeMember(name=m_ast[2], oftype=m_ast[1], value=m_ast[3])
+        return OFTypeMember(name=m_ast[2], oftype=get_type(m_ast[1], ctx), value=m_ast[3])
     elif m_ast[0] == 'data':
         if m_ast[2] == 'length' or m_ast[2] == 'len': # Should be moved to parser
-            return OFLengthMember(name=m_ast[2], oftype=m_ast[1])
+            return OFLengthMember(name=m_ast[2], oftype=get_type(m_ast[1], ctx))
         elif m_ast[2] == 'actions_len':
             # HACK only usage so far
-            return OFFieldLengthMember(name=m_ast[2], oftype=m_ast[1], field_name='actions')
+            return OFFieldLengthMember(name=m_ast[2], oftype=get_type(m_ast[1], ctx), field_name='actions')
         else:
-            return OFDataMember(name=m_ast[2], oftype=m_ast[1])
+            return OFDataMember(name=m_ast[2], oftype=get_type(m_ast[1], ctx))
     elif m_ast[0] == 'discriminator':
-        return OFDiscriminatorMember(name=m_ast[2], oftype=m_ast[1])
+        return OFDiscriminatorMember(name=m_ast[2], oftype=get_type(m_ast[1], ctx))
     else:
         raise InputError("Dont know how to create member: %s" % m_ast[0])
 
 def create_ofinput(ast):
+
     """
     Create an OFInput from an AST
 
@@ -59,7 +71,7 @@
 
     @returns An OFInput object
     """
-
+    ctx = FrontendCtx(set())
     ofinput = OFInput(wire_versions=set(), classes=[], enums=[])
 
     for decl_ast in ast:
@@ -70,7 +82,7 @@
             # 3: super_class or None
             # 4: list of members
             superclass = decl_ast[3]
-            members = [create_member(m_ast) for m_ast in decl_ast[4]]
+            members = [create_member(m_ast, ctx) for m_ast in decl_ast[4]]
 
             discriminators = [ m for m in members if isinstance(m, OFDiscriminatorMember) ]
             if len(discriminators) > 1:
@@ -103,4 +115,8 @@
     if not ofinput.wire_versions:
         raise InputError("Missing #version metadata")
 
+    for used_enum in ctx.used_enums:
+        if not find(lambda e: e.name == used_enum, ofinput.enums):
+            raise Exception("Undeclared enum used in OFInput: {}".format(used_enum))
+
     return ofinput
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index 25bfde4..f2cf4b0 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -44,10 +44,11 @@
 identifier = word.copy().setName("identifier")
 
 # Type names
-scalar_type = word
-array_type = P.Combine(word + lit('[') - P.Word(P.alphanums + '_') - lit(']'))
-list_type = P.Combine(kw('list') - lit('(') - identifier - lit(')'))
-any_type = (array_type | list_type | scalar_type).setName("type name")
+enum_type = kw("enum") - word
+scalar_type = tag("scalar") + word
+array_type = tag("array") + P.Combine(word + lit('[') - P.Word(P.alphanums + '_') - lit(']'))
+list_type = tag("list") + P.Combine(kw('list') - lit('(') - identifier - lit(')'))
+any_type = P.Group(enum_type | array_type | list_type | scalar_type).setName("type name")
 
 # Structs
 pad_member = P.Group(kw('pad') - s('(') - integer - s(')'))
@@ -56,7 +57,7 @@
 data_member = P.Group(tag('data') + any_type - identifier)
 
 struct_param_name = kw("align")
-struct_param = P.Group(struct_param_name - s('=') - any_type)
+struct_param = P.Group(struct_param_name - s('=') - word)
 struct_param_list = P.Forward()
 struct_param_list << struct_param + P.Optional(s(',') - P.Optional(struct_param_list))
 
@@ -68,12 +69,12 @@
 
 # Enums
 enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete")
-enum_param = P.Group(enum_param_name  - s('=') - any_type)
+enum_param = P.Group(enum_param_name  - s('=') - word)
 enum_param_list = P.Forward()
 enum_param_list << enum_param + P.Optional(s(',') + P.Optional(enum_param_list))
 
 enum_member_param_name = kw("virtual")
-enum_member_param = P.Group(enum_member_param_name  - s('=') - any_type)
+enum_member_param = P.Group(enum_member_param_name  - s('=') - word)
 enum_member_param_list = P.Forward()
 enum_member_param_list << enum_member_param + P.Optional(s(',') + P.Optional(enum_member_param_list))
 
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 938b7dd..4a73261 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -159,7 +159,7 @@
     OFPFW_NW_DST_MASK = 0xfc000,
     OFPFW_DL_VLAN_PCP = 0x100000,
     OFPFW_NW_TOS = 0x200000,
-    OFPFW_ALL = 0x3fffff,
+    OFPFW_ALL(virtual=True) = 0x3fffff,
 };
 
 enum ofp_action_type(wire_type=uint16_t) {
@@ -586,7 +586,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
@@ -603,7 +603,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
@@ -620,7 +620,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
@@ -637,7 +637,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
@@ -654,7 +654,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
@@ -671,7 +671,7 @@
     uint16_t priority;
     uint32_t buffer_id;
     of_port_no_t out_port;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     list(of_action_t) actions;
 };
 
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index bbf2277..9acbacf 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -856,7 +856,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -877,7 +877,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -898,7 +898,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -919,7 +919,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -940,7 +940,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -961,7 +961,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 703a969..9752b7d 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -772,7 +772,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -793,7 +793,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -814,7 +814,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -835,7 +835,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -856,7 +856,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -877,7 +877,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index e0f08b6..afe371e 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -924,7 +924,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -945,7 +945,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -966,7 +966,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -987,7 +987,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -1008,7 +1008,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
@@ -1029,7 +1029,7 @@
     uint32_t buffer_id;
     of_port_no_t out_port;
     uint32_t out_group;
-    ofp_flow_mod_flags flags;
+    enum ofp_flow_mod_flags flags;
     pad(2);
     of_match_t match;
     list(of_instruction_t) instructions;
diff --git a/utest/test_frontend.py b/utest/test_frontend.py
index 8799000..8febfde 100755
--- a/utest/test_frontend.py
+++ b/utest/test_frontend.py
@@ -91,21 +91,21 @@
                 ['OFPPC_NO_PACKET_IN', [], 64]]],
             ['metadata', 'version', '2'],
             ['struct', 'of_echo_reply', [['align', '8']], None, [
-                ['data', 'uint8_t', 'version'],
-                ['type', 'uint8_t', 'type', 3],
-                ['data', 'uint16_t', 'length'],
-                ['data', 'uint32_t', 'xid'],
-                ['data', 'of_octets_t', 'data']]],
+                ['data', ['scalar', 'uint8_t'], 'version'],
+                ['type', ['scalar', 'uint8_t'], 'type', 3],
+                ['data', ['scalar', 'uint16_t'], 'length'],
+                ['data', ['scalar', 'uint32_t'], 'xid'],
+                ['data', ['scalar', 'of_octets_t'], 'data']]],
             ['enum', 'ofp_queue_op_failed_code',
                 [['wire_type', 'uint32'], ['bitmask','False'], ['complete', 'True']], [
                 ['OFPQOFC_BAD_PORT', [], 0],
                 ['OFPQOFC_BAD_QUEUE', [], 1],
                 ['OFPQOFC_EPERM', [], 2]]],
             ['struct', 'of_packet_queue', [], None, [
-                ['data', 'uint32_t', 'queue_id'],
-                ['data', 'uint16_t', 'len'],
+                ['data', ['scalar', 'uint32_t'], 'queue_id'],
+                ['data', ['scalar', 'uint16_t'], 'len'],
                 ['pad', 2],
-                ['data', 'list(of_queue_prop_t)', 'properties']]],
+                ['data', ['list', 'list(of_queue_prop_t)'], 'properties']]],
         ]
         self.assertEquals(expected_ast, ast)
 
@@ -167,15 +167,15 @@
             ['metadata', 'version', '1'],
 
             ['struct', 'of_queue_prop', [], None, [
-                ['discriminator', 'uint16_t', 'type'],
-                ['data', 'uint16_t', 'len'],
+                ['discriminator', ['scalar', 'uint16_t'], 'type'],
+                ['data', ['scalar', 'uint16_t'], 'len'],
                 ['pad', 4]]],
 
             ['struct', 'of_queue_prop_min_rate', [], 'of_queue_prop', [
-                ['type', 'uint16_t', 'type', 1],
-                ['data', 'uint16_t', 'len'],
+                ['type', ['scalar', 'uint16_t'], 'type', 1],
+                ['data', ['scalar', 'uint16_t'], 'len'],
                 ['pad', 4],
-                ['data', 'uint16_t', 'rate'],
+                ['data', ['scalar', 'uint16_t'], 'rate'],
                 ['pad', 6]]],
         ]
         self.assertEquals(expected_ast, ast)
diff --git a/utest/test_parser.py b/utest/test_parser.py
index 9eb3764..8acfdda 100755
--- a/utest/test_parser.py
+++ b/utest/test_parser.py
@@ -52,7 +52,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['data', 'uint32_t', 'bar']]]])
+            [['struct', 'foo', [], None, [['data', ['scalar', 'uint32_t'], 'bar']]]])
 
     def test_struct_align_arg(self):
         src = """\
@@ -62,7 +62,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [['align', '8']], None, [['data', 'uint32_t', 'bar']]]])
+            [['struct', 'foo', [['align', '8']], None, [['data', ['scalar', 'uint32_t'], 'bar']]]])
 
     def test_multiple_fields(self):
         src = """\
@@ -75,9 +75,9 @@
         ast = parser.parse(src)
         self.assertEquals(ast,
             [['struct', 'foo', [], None,
-                [['data', 'uint32_t', 'bar'],
-                 ['data', 'uint8_t', 'baz'],
-                 ['data', 'uint64_t', 'abc']]]])
+                [['data', ['scalar', 'uint32_t'], 'bar'],
+                 ['data', ['scalar', 'uint8_t'], 'baz'],
+                 ['data', ['scalar', 'uint64_t'], 'abc']]]])
 
     def test_array_type(self):
         src = """\
@@ -87,7 +87,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['data', 'uint32_t[4]', 'bar']]]])
+            [['struct', 'foo', [], None, [['data', ['array', 'uint32_t[4]'], 'bar']]]])
 
     def test_list_type(self):
         src = """\
@@ -97,7 +97,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['data', 'list(of_action_t)', 'bar']]]])
+            [['struct', 'foo', [], None, [['data', ['list', 'list(of_action_t)'], 'bar']]]])
 
     def test_pad_member(self):
         src = """\
@@ -117,7 +117,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['type', 'uint16_t', 'foo', 0x10]]]])
+            [['struct', 'foo', [], None, [['type', ['scalar', 'uint16_t'], 'foo', 0x10]]]])
 
     def test_inheritance(self):
         src = """\
@@ -127,7 +127,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], 'bar', [['type', 'uint16_t', 'foo', 0x10]]]])
+            [['struct', 'foo', [], 'bar', [['type', ['scalar', 'uint16_t'], 'foo', 0x10]]]])
 
     def test_discriminator(self):
         src = """\
@@ -137,7 +137,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['discriminator', 'uint16_t', 'foo']]]])
+            [['struct', 'foo', [], None, [['discriminator', ['scalar', 'uint16_t'], 'foo']]]])
 
 class EnumTests(unittest.TestCase):
     def test_empty(self):
@@ -220,7 +220,7 @@
 """
         ast = parser.parse(src)
         self.assertEquals(ast,
-            [['struct', 'foo', [], None, [['data', 'uint32_t', 'a']]]])
+            [['struct', 'foo', [], None, [['data', ['scalar', 'uint32_t'], 'a']]]])
 
     def test_mixed(self):
         src = """\