frontend: parse enums from input files
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index 6b0e1eb..974e6cf 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -51,11 +51,19 @@
          P.Group(P.ZeroOrMore(struct_member)) + \
          s('}') - s(';')
 
+# Enums
+enum_member = P.Group(identifier + s('=') + P.Word(P.alphanums + '_'))
+enum_list = P.Forward()
+enum_list << enum_member + P.Optional(s(',') + P.Optional(enum_list))
+enum = kw('enum') - identifier - s('{') + \
+         P.Group(P.Optional(enum_list)) + \
+         s('}') - s(';')
+
 # Metadata
 metadata_key = P.Or(kw("version")).setName("metadata key")
 metadata = tag('metadata') + s('#') - metadata_key - word
 
-grammar = P.ZeroOrMore(P.Group(struct) | P.Group(metadata))
+grammar = P.ZeroOrMore(P.Group(struct) | P.Group(enum) | P.Group(metadata))
 grammar.ignore(P.cppStyleComment)
 
 def parse(src):
diff --git a/utest/test_parser.py b/utest/test_parser.py
index 75e0c5d..91100ab 100755
--- a/utest/test_parser.py
+++ b/utest/test_parser.py
@@ -83,6 +83,46 @@
         self.assertEquals(ast.asList(),
             [['struct', 'foo', [['list(of_action_t)', 'bar']]]])
 
+class EnumTests(unittest.TestCase):
+    def test_empty(self):
+        src = """\
+enum foo {
+};
+"""
+        ast = parser.parse(src)
+        self.assertEquals(ast.asList(), [['enum', 'foo', []]])
+
+    def test_one(self):
+        src = """\
+enum foo {
+    BAR = 1
+};
+"""
+        ast = parser.parse(src)
+        self.assertEquals(ast.asList(), [['enum', 'foo', [['BAR', '1']]]])
+
+    def test_multiple(self):
+        src = """\
+enum foo {
+    OFP_A = 1,
+    OFP_B = 2,
+    OFP_C = 3
+};
+"""
+        ast = parser.parse(src)
+        self.assertEquals(ast.asList(), [['enum', 'foo', [['OFP_A', '1'], ['OFP_B', '2'], ['OFP_C', '3']]]])
+
+    def test_trailing_comma(self):
+        src = """\
+enum foo {
+    OFP_A = 1,
+    OFP_B = 2,
+    OFP_C = 3,
+};
+"""
+        ast = parser.parse(src)
+        self.assertEquals(ast.asList(), [['enum', 'foo', [['OFP_A', '1'], ['OFP_B', '2'], ['OFP_C', '3']]]])
+
 class TestMetadata(unittest.TestCase):
     def test_version(self):
         src = """\