blob: c778448430fcb9e0ac0d204518bd4741195fb02a [file] [log] [blame]
Sapan Bhatia64c72512017-06-23 02:32:45 -07001__author__ = "Sapan Bhatia"
2
3__copyright__ = "Copyright (C) 2017 Open Networking Lab"
4__version__ = "1.0"
5
6import ply.lex as lex
7import ply.yacc as yacc
8
9from helpers import LexHelper, LU
10
11class FOLLexer(object):
Sapan Bhatiacee04022017-07-20 02:12:43 -040012 keywords = ('forall', 'exists', 'True', 'False', 'not', 'in')
Sapan Bhatia64c72512017-06-23 02:32:45 -070013
Sapan Bhatia99669732017-07-25 19:19:14 -040014 tokens = ['STRING_LITERAL', 'NUM', 'ESCAPE', 'COLON', 'IMPLIES', 'OR', 'AND', 'LPAREN', 'RPAREN', 'EQUALS', 'SYMBOL', 'LT', 'RT', 'STAR'] + [k.upper() for k in keywords]
Sapan Bhatia64c72512017-06-23 02:32:45 -070015 # literals = '()+-*/=?:,.^|&~!=[]{};<>@%'
16
17 t_ignore_LINE_COMMENT = '//.*'
18 t_COLON = '\\:'
19 t_IMPLIES = '\\-\\>'
20 t_OR = '\\|'
Sapan Bhatia99669732017-07-25 19:19:14 -040021 t_STAR = '\\*'
Sapan Bhatia64c72512017-06-23 02:32:45 -070022 t_LT = '\\<'
23 t_RT = '\\>'
24 t_AND = '\\&'
25 t_LPAREN = '\\('
26 t_RPAREN = '\\)'
Sapan Bhatiafc1278c2017-07-17 12:57:13 -040027 t_NUM = r'[+-]?\d+(\.\d+)?'
28 t_STRING_LITERAL = r'\"([^\\\n]|(\\.))*?\"'
Sapan Bhatia64c72512017-06-23 02:32:45 -070029
30 t_EQUALS = '\\='
31
32 literals = '()+-*/=?:,.^|&~!=[]{};<>@%'
33
34 t_ignore = ' \t\f'
35
36 def t_newline(self, t):
37 r'\n+'
38 t.lexer.lineno += len(t.value)
39
40 def t_newline2(self, t):
41 r'(\r\n)+'
42 t.lexer.lineno += len(t.value) / 2
43
44 t_ESCAPE = r'{{ (.|\n)*? }}'
45
46 def t_BLOCK_COMMENT(self, t):
47 r'/\*(.|\n)*?\*/'
48 t.lexer.lineno += t.value.count('\n')
49
50 def t_SYMBOL(self, t):
Sapan Bhatia99669732017-07-25 19:19:14 -040051 '[A-Za-z_$][\.A-Za-z0-9_+$]*(\(\))?'
Sapan Bhatia64c72512017-06-23 02:32:45 -070052 if t.value in FOLLexer.keywords:
53 t.type = t.value.upper()
54 return t
55
56 def t_error(self, t):
57 print("Illegal character '{}' ({}) in line {}".format(t.value[0], hex(ord(t.value[0])), t.lexer.lineno))
58 t.lexer.skip(1)
59
60
61
62class FOLParser(object):
63 tokens = FOLLexer.tokens
64 offset = 0
65 lh = LexHelper()
66
67 def setOffset(self, of):
68 self.offset = of
69 self.lh.offset = of
70
Sapan Bhatiafc1278c2017-07-17 12:57:13 -040071 def p_term_numeric_constant(self, p):
72 '''term : NUM'''
73 p[0] = p[1]
74
75 def p_term_string_constant(self, p):
76 '''term : STRING_LITERAL'''
77 p[0] = p[1]
78
79 def p_term_boolean_constant(self, p):
Sapan Bhatia64c72512017-06-23 02:32:45 -070080 '''term : FALSE
81 | TRUE'''
82 p[0] = p[1]
83
Sapan Bhatia99669732017-07-25 19:19:14 -040084 def p_term_policy_function(self, p):
85 '''term : STAR SYMBOL LPAREN SYMBOL RPAREN'''
86 p[0] = {'policy': [p[2], p[4]]}
87
Sapan Bhatia64c72512017-06-23 02:32:45 -070088 def p_fole_not(self, p):
89 '''fole : NOT fole'''
90 p[0] = {p[1]: p[2]}
91
92 def p_fole_term(self, p):
93 '''fole : term'''
94 p[0] = p[1]
95
96 def p_term_symbol(self, p):
97 '''term : SYMBOL'''
98 p[0] = p[1]
99
100 def p_term_python(self, p):
Sapan Bhatiab934f722017-07-15 08:42:19 -0400101 '''term : ESCAPE'''
Sapan Bhatiabc6268c2017-07-16 02:43:45 -0400102 p[0] = {'python': p[1].lstrip('{ ').rstrip(' }')}
Sapan Bhatia64c72512017-06-23 02:32:45 -0700103
104 def p_fole_group(self, p):
105 "fole : LPAREN fole RPAREN"
106 p[0] = p[2]
107
Sapan Bhatiacee04022017-07-20 02:12:43 -0400108 def p_fole_in(self, p):
109 "fole : term IN term"
110 p[0] = {'in': (p[1], p[3])}
111
Sapan Bhatia64c72512017-06-23 02:32:45 -0700112 def p_fole_equals(self, p):
113 "fole : term EQUALS term"
114 p[0] = {'=': (p[1], p[3])}
115
116 def p_fole_binary(self, p):
117 '''fole : fole AND fole
118 | fole OR fole
119 | fole IMPLIES fole'''
120 p[0] = {p[2]: [p[1], p[3]]}
121
122 def p_fole_quant(self, p):
123 '''fole : FORALL SYMBOL COLON fole
124 | EXISTS SYMBOL COLON fole'''
125 p[0] = {p[1]: [p[2], p[4]]}
126
127
128 def p_goal(self, p):
129 '''goal : LT fole RT'''
130 p[0] = p[2]
131
132 def p_error(self, p):
133 print('error: {}'.format(p))
134