-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGrammar.gram
81 lines (70 loc) · 3.21 KB
/
Grammar.gram
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
# RETRIEVED AND MODIFIED FROM https://docs.python.org/3.7/reference/grammar.html
# Grammar for Python
# NOTE WELL: You should also follow all the steps listed at
# https://devguide.python.org/grammar/
# Start symbols for the grammar:
# single_input is a single interactive statement;
# file_input is a module or sequence of commands read from an input file;
# eval_input is the input for the eval() functions.
# NB: compound_stmt in single_input is followed by extra NEWLINE!
# single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
file_input: (NEWLINE | stmt)* ENDMARKER
# eval_input: test NEWLINE* ENDMARKER
funcdef: 'def' NAME parameters ':' suite
parameters: '(' [varargslist] ')'
varargslist: NAME ("," NAME)*
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (assign_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
assign_stmt: NAME annassign
annassign: ':' test ['=' test]
# For normal and annotated assignments, additional restrictions enforced by the interpreter
pass_stmt: 'pass'
flow_stmt: break_stmt | continue_stmt | return_stmt
break_stmt: 'break'
continue_stmt: 'continue'
return_stmt: 'return' [test]
import_stmt: import_from
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
import_from: 'from' NAME 'import' (NAME | parameters)
global_stmt: 'global' NAME (',' NAME)*
nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
assert_stmt: 'assert' test [',' test]
compound_stmt: if_stmt | while_stmt | for_stmt | funcdef
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ((':' test) | ('::' suite))
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: arith_expr (comp_op arith_expr)*
# <> isn't actually a valid comparison operator in Python. It's here for the
# sake of a __future__ import described in PEP 401 (which really works :-)
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
star_expr: '*' arith_expr
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom_expr ['**' factor]
atom_expr: atom [arglist]
atom: ('(' [testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
subscript: test | [test] ':' [test] [sliceop]
sliceop: ':' [test]
exprlist: (arith_expr|star_expr) (',' (arith_expr|star_expr))* [',']
comp_iter: comp_for | comp_if
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
comp_for: sync_comp_for
comp_if: 'if' test_nocond [comp_iter]
arglist: '(' test (',' test)* ')'
# not used in grammar, but may appear in "node" passed from Parser to Compiler
encoding_decl: NAME