-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsParser.py
164 lines (124 loc) · 3.17 KB
/
jsParser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
from jsLexer import *
import ply.yacc as yacc
start = 'js'
precedence = (
('left','OROR'),
('left','ANDAND'),
('left','EQUALEQUAL'),
('left','LT','LE','GT','GE'),
('left','PLUS','MINUS'),
('left','TIMES','DIVIDE','MOD'),
('right','NOT'),
)
def p_js(p):
'js : element js'
p[0] = [p[1]] + p[2]
def p_js_empty(p):
'js : '
p[0] = []
def p_element_function(p):
'element : FUNCTION IDENTIFIER LPAREN optparams RPAREN compoundstmt'
p[0] = ('function',p[2],p[4],p[6])
def p_element_stmt(p):
'element : stmt SEMICOLON'
p[0] = ("stmt",p[1])
def p_optparams(p):
'optparams : params'
p[0] = p[1]
def p_optparams_empty(p):
'optparams : '
p[0] = []
def p_params(p):
'params : IDENTIFIER COMMA params'
p[0] = [p[1]] + p[3]
def p_params_one(p):
'params : IDENTIFIER'
p[0] = [p[1]]
def p_compoundstmt(p):
'compoundstmt : LBRACE stmts RBRACE'
p[0] = p[2]
def p_stmts_empty(p):
'stmts : '
p[0] = []
def p_stmts(p):
'stmts : stmt SEMICOLON stmts'
p[0] = [p[1]] + p[3]
def p_stmt_if(p):
'stmt : IF exp compoundstmt'
p[0] = ('if-then',p[2],p[3])
def p_stmt_if_else(p):
'stmt : IF exp compoundstmt ELSE compoundstmt'
p[0] = ('if-then-else',p[2],p[3],p[5])
def p_stmt_assigment(p):
'stmt : IDENTIFIER EQUAL exp'
p[0] = ('assign',p[1],p[3])
def p_stmt_return(p):
'stmt : RETURN exp'
p[0] = ("return",p[2])
def p_stmt_var(p):
'stmt : VAR IDENTIFIER EQUAL exp'
p[0] = ("var",p[2],p[4])
def p_stmt_exp(p):
'stmt : exp'
p[0] = ('exp',p[1])
# experession
def p_exp_identifier(p):
'exp : IDENTIFIER'
p[0] = ("identifier",p[1])
def p_exp_number(p):
'exp : NUMBER'
p[0] = ('number',p[1])
def p_exp_string(p):
'exp : STRING'
p[0] = ('string',p[1])
def p_exp_true(p):
'exp : TRUE'
p[0] = ('true','true')
def p_exp_false(p):
'exp : FALSE'
p[0] = ('false','false')
def p_exp_not(p):
'exp : NOT exp'
p[0] = ('not', p[2])
def p_exp_parens(p):
'exp : LPAREN exp RPAREN'
p[0] = p[2]
def p_exp_binop(p):
'''exp : exp PLUS exp
| exp MINUS exp
| exp TIMES exp
| exp MOD exp
| exp DIVIDE exp
| exp EQUALEQUAL exp
| exp LE exp
| exp LT exp
| exp GE exp
| exp GT exp
| exp ANDAND exp
| exp OROR exp
'''
p[0] = ('binop',p[1],p[2],p[3])
def p_exp_call(p):
'exp : IDENTIFIER LPAREN optargs RPAREN'
p[0] = ('call',p[1],p[3])
def p_exp_optargs(p):
'optargs : args'
p[0] = p[1]
def p_optargs_empty(p):
'optargs : '
p[0] = []
def p_args(p):
'args : exp COMMA args'
p[0] = [p[1]] + p[3]
def p_args_one(p):
'args : exp'
p[0] = [p[1]]
jsparser = yacc.yacc()
def test_parser(input_string):
jslexer.input(input_string)
parse_tree = jsparser.parse(input_string,lexer=jslexer)
return parse_tree
# Simple function with no arguments and a one-statement body.
jstext1 = "function myfun() { return nothing ; }"
jstree1 = [('function', 'myfun', [], [('return', ('identifier', 'nothing'))])]
print test_parser(jstext1) == jstree1