blob: 30b1bf6c99e0f7e2de5f6e7e3479c788ec060f1b [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 Bhatiafc1278c2017-07-17 12:57:13 -040014 tokens = ['STRING_LITERAL', 'NUM', 'ESCAPE', 'COLON', 'IMPLIES', 'OR', 'AND', 'LPAREN', 'RPAREN', 'EQUALS', 'SYMBOL', 'LT', 'RT'] + [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 = '\\|'
21 t_LT = '\\<'
22 t_RT = '\\>'
23 t_AND = '\\&'
24 t_LPAREN = '\\('
25 t_RPAREN = '\\)'
Sapan Bhatiafc1278c2017-07-17 12:57:13 -040026 t_NUM = r'[+-]?\d+(\.\d+)?'
27 t_STRING_LITERAL = r'\"([^\\\n]|(\\.))*?\"'
Sapan Bhatia64c72512017-06-23 02:32:45 -070028
29 t_EQUALS = '\\='
30
31 literals = '()+-*/=?:,.^|&~!=[]{};<>@%'
32
33 t_ignore = ' \t\f'
34
35 def t_newline(self, t):
36 r'\n+'
37 t.lexer.lineno += len(t.value)
38
39 def t_newline2(self, t):
40 r'(\r\n)+'
41 t.lexer.lineno += len(t.value) / 2
42
43 t_ESCAPE = r'{{ (.|\n)*? }}'
44
45 def t_BLOCK_COMMENT(self, t):
46 r'/\*(.|\n)*?\*/'
47 t.lexer.lineno += t.value.count('\n')
48
49 def t_SYMBOL(self, t):
Sapan Bhatiacee04022017-07-20 02:12:43 -040050 '[A-Za-z_$][\.A-Za-z2-9_+$]*(\(\))?'
Sapan Bhatia64c72512017-06-23 02:32:45 -070051 if t.value in FOLLexer.keywords:
52 t.type = t.value.upper()
53 return t
54
55 def t_error(self, t):
56 print("Illegal character '{}' ({}) in line {}".format(t.value[0], hex(ord(t.value[0])), t.lexer.lineno))
57 t.lexer.skip(1)
58
59
60
61class FOLParser(object):
62 tokens = FOLLexer.tokens
63 offset = 0
64 lh = LexHelper()
65
66 def setOffset(self, of):
67 self.offset = of
68 self.lh.offset = of
69
Sapan Bhatiafc1278c2017-07-17 12:57:13 -040070 def p_term_numeric_constant(self, p):
71 '''term : NUM'''
72 p[0] = p[1]
73
74 def p_term_string_constant(self, p):
75 '''term : STRING_LITERAL'''
76 p[0] = p[1]
77
78 def p_term_boolean_constant(self, p):
Sapan Bhatia64c72512017-06-23 02:32:45 -070079 '''term : FALSE
80 | TRUE'''
81 p[0] = p[1]
82
83 def p_fole_not(self, p):
84 '''fole : NOT fole'''
85 p[0] = {p[1]: p[2]}
86
87 def p_fole_term(self, p):
88 '''fole : term'''
89 p[0] = p[1]
90
91 def p_term_symbol(self, p):
92 '''term : SYMBOL'''
93 p[0] = p[1]
94
95 def p_term_python(self, p):
Sapan Bhatiab934f722017-07-15 08:42:19 -040096 '''term : ESCAPE'''
Sapan Bhatiabc6268c2017-07-16 02:43:45 -040097 p[0] = {'python': p[1].lstrip('{ ').rstrip(' }')}
Sapan Bhatia64c72512017-06-23 02:32:45 -070098
99 def p_fole_group(self, p):
100 "fole : LPAREN fole RPAREN"
101 p[0] = p[2]
102
Sapan Bhatiacee04022017-07-20 02:12:43 -0400103 def p_fole_in(self, p):
104 "fole : term IN term"
105 p[0] = {'in': (p[1], p[3])}
106
Sapan Bhatia64c72512017-06-23 02:32:45 -0700107 def p_fole_equals(self, p):
108 "fole : term EQUALS term"
109 p[0] = {'=': (p[1], p[3])}
110
111 def p_fole_binary(self, p):
112 '''fole : fole AND fole
113 | fole OR fole
114 | fole IMPLIES fole'''
115 p[0] = {p[2]: [p[1], p[3]]}
116
117 def p_fole_quant(self, p):
118 '''fole : FORALL SYMBOL COLON fole
119 | EXISTS SYMBOL COLON fole'''
120 p[0] = {p[1]: [p[2], p[4]]}
121
122
123 def p_goal(self, p):
124 '''goal : LT fole RT'''
125 p[0] = p[2]
126
127 def p_error(self, p):
128 print('error: {}'.format(p))
129