CORD-1320: Implement pure protobuf support for policies

Change-Id: Ifaeba28d1aea46cb9f9f674d75c6c65cf104435f
diff --git a/lib/xos-genx/Makefile b/lib/xos-genx/Makefile
index 70ae716..898f154 100644
--- a/lib/xos-genx/Makefile
+++ b/lib/xos-genx/Makefile
@@ -1,2 +1,3 @@
 test:
-	nosetests -s -v --with-id
\ No newline at end of file
+	nosetests -s -v --with-id
+
diff --git a/lib/xos-genx/tests/pure_proto_test.py b/lib/xos-genx/tests/pure_proto_test.py
index 836b0b0..1f165fb 100644
--- a/lib/xos-genx/tests/pure_proto_test.py
+++ b/lib/xos-genx/tests/pure_proto_test.py
@@ -83,6 +83,34 @@
 
 		self.assertEqual(count1, count2)
 
+    def test_pure_policies(self):
+		xproto = \
+"""
+policy my_policy < exists x:a=b >
+"""
+
+		proto = \
+"""
+option my_policy = "policy:< exists x:a=b >";
+"""
+		target = XProtoTestHelpers.write_tmp_target(
+"""
+{{ policies }}
+""")
+
+		args_xproto = FakeArgs()
+		args_xproto.inputs = xproto
+		args_xproto.target = target
+		xproto_gen = XOSGenerator.generate(args_xproto)
+
+		args_proto = FakeArgs()
+		args_proto.inputs = proto
+		args_proto.target = target
+		args_proto.rev = True
+		proto_gen = XOSGenerator.generate(args_proto)
+
+		self.assertEqual(proto_gen, xproto_gen)
+
 if __name__ == '__main__':
     unittest.main()
 
diff --git a/lib/xos-genx/xosgenx/proto2xproto.py b/lib/xos-genx/xosgenx/proto2xproto.py
index 3723e7c..ffdb5d1 100644
--- a/lib/xos-genx/xosgenx/proto2xproto.py
+++ b/lib/xos-genx/xosgenx/proto2xproto.py
@@ -3,10 +3,13 @@
 import pdb
 import argparse
 import plyxproto.parser as plyxproto
+from plyxproto.logicparser import FOLParser, FOLLexer
 import traceback
 import sys
 import jinja2
 import os
+import ply.lex as lex
+import ply.yacc as yacc
 
 class Stack(list):
     def push(self,x):
@@ -23,6 +26,7 @@
 
     return {'name': name, 'package': package, 'fqn': s}
 
+
 def replace_link(obj):
         try:
             link = obj.link
@@ -49,6 +53,9 @@
             return obj
 
 class Proto2XProto(Visitor):
+    fol_lexer = lex.lex(module=FOLLexer())
+    fol_parser = yacc.yacc(module=FOLParser(), start='goal')
+
     def __init__(self):
         super(Proto2XProto, self).__init__()
 
@@ -67,6 +74,20 @@
         self.first_field = True
         self.first_method = True
     
+    def replace_policy(self, obj):
+        if isinstance(obj, m.OptionStatement):
+            rhs = obj.value.value.pval
+            if rhs.startswith('"') and rhs.endswith('"'):
+                rhs = rhs[1:-1]
+
+            if rhs.startswith('policy:'):
+                str = rhs.split(':')[1]
+                val = self.fol_parser.parse(str, lexer = self.fol_lexer)
+
+                return m.PolicyDefinition(obj.name, val)
+
+        return obj
+
     def proto_to_xproto_field(self, obj):
         try:
             opts = {}
@@ -83,7 +104,11 @@
 
     def proto_to_xproto_message(self, obj):
         try:
-            bases = self.message_options['bases'].split(',')
+            try:
+                bases = self.message_options['bases'].split(',')
+            except KeyError:
+                bases = []
+
             bases = map(lambda x:str_to_dict(x[1:-1]), bases)
             obj.bases = bases
         except KeyError:
@@ -191,6 +216,8 @@
         return True
     
     def visit_Proto_post(self, obj):
+
+        obj.body = [self.replace_policy(o) for o in obj.body]
         return True
 
     def visit_LinkSpec(self, obj):