Skip to content

Commit a27bc28

Browse files
committed
Implement For and If
1 parent b685896 commit a27bc28

File tree

3 files changed

+103
-11
lines changed

3 files changed

+103
-11
lines changed

parser/grammar.y

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr {
6464
alias *ast.Alias
6565
aliases []*ast.Alias
6666
identifiers []ast.Identifier
67+
ifstmt *ast.If
68+
lastif *ast.If
6769
}
6870

6971
%type <obj> strings
7072
%type <mod> inputs file_input single_input eval_input
71-
%type <stmts> simple_stmt stmt nl_or_stmt small_stmts stmts
72-
%type <stmt> compound_stmt small_stmt expr_stmt del_stmt pass_stmt flow_stmt import_stmt global_stmt nonlocal_stmt assert_stmt break_stmt continue_stmt return_stmt raise_stmt yield_stmt import_name import_from
73+
%type <stmts> simple_stmt stmt nl_or_stmt small_stmts stmts suite optional_else
74+
%type <stmt> compound_stmt small_stmt expr_stmt del_stmt pass_stmt flow_stmt import_stmt global_stmt nonlocal_stmt assert_stmt break_stmt continue_stmt return_stmt raise_stmt yield_stmt import_name import_from while_stmt if_stmt for_stmt
7375
%type <op> augassign
7476
%type <expr> expr_or_star_expr expr star_expr xor_expr and_expr shift_expr arith_expr term factor power trailer atom test_or_star_expr test not_test lambdef test_nocond lambdef_nocond or_test and_test comparison testlist testlist_star_expr yield_expr_or_testlist yield_expr yield_expr_or_testlist_star_expr dictorsetmaker sliceop arglist
7577
%type <exprs> exprlist testlistraw comp_if comp_iter expr_or_star_exprs test_or_star_exprs tests test_colon_tests trailers
@@ -83,6 +85,7 @@ func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr {
8385
%type <identifiers> names
8486
%type <alias> dotted_as_name import_as_name
8587
%type <aliases> dotted_as_names import_as_names import_from_arg
88+
%type <ifstmt> elifs
8689

8790
%token NEWLINE
8891
%token ENDMARKER
@@ -932,7 +935,7 @@ compound_stmt:
932935
}
933936
| while_stmt
934937
{
935-
// FIXME
938+
$$ = $1
936939
}
937940
| for_stmt
938941
{
@@ -961,38 +964,63 @@ compound_stmt:
961964

962965
elifs:
963966
{
964-
// FIXME
967+
$$ = nil
968+
$<lastif>$ = nil
965969
}
966970
| elifs ELIF test ':' suite
967971
{
968-
// FIXME
972+
elifs := $$
973+
newif := &ast.If{StmtBase: ast.StmtBase{$<pos>$}, Test: $3, Body: $5}
974+
if elifs == nil {
975+
$$ = newif
976+
} else {
977+
$<lastif>$.Orelse = []ast.Stmt{newif}
978+
}
979+
$<lastif>$ = newif
969980
}
970981

971982
optional_else:
972983
{
973-
// FIXME
984+
$$ = nil
974985
}
975986
| ELSE ':' suite
976987
{
977-
// FIXME
988+
$$ = $3
978989
}
979990

980991
if_stmt:
981992
IF test ':' suite elifs optional_else
982993
{
983-
// FIXME
994+
newif := &ast.If{StmtBase: ast.StmtBase{$<pos>$}, Test: $2, Body: $4}
995+
$$ = newif
996+
elifs := $5
997+
optional_else := $6
998+
if len(optional_else) != 0 {
999+
if elifs != nil {
1000+
$<lastif>5.Orelse = optional_else
1001+
newif.Orelse = []ast.Stmt{elifs}
1002+
} else {
1003+
newif.Orelse = optional_else
1004+
}
1005+
} else {
1006+
if elifs != nil {
1007+
newif.Orelse = []ast.Stmt{elifs}
1008+
}
1009+
}
9841010
}
9851011

9861012
while_stmt:
9871013
WHILE test ':' suite optional_else
9881014
{
989-
// FIXME
1015+
$$ = &ast.While{StmtBase: ast.StmtBase{$<pos>$}, Test: $2, Body: $4, Orelse: $5}
9901016
}
9911017

9921018
for_stmt:
9931019
FOR exprlist IN testlist ':' suite optional_else
9941020
{
995-
// FIXME
1021+
target := tupleOrExpr($<pos>$, $2, false)
1022+
target.(ast.SetCtxer).SetCtx(ast.Store)
1023+
$$ = &ast.For{StmtBase: ast.StmtBase{$<pos>$}, Target: target, Iter: $4, Body: $6, Orelse: $7}
9961024
}
9971025

9981026
except_clauses:
@@ -1076,9 +1104,12 @@ stmts:
10761104

10771105
suite:
10781106
simple_stmt
1107+
{
1108+
$$ = $1
1109+
}
10791110
| NEWLINE INDENT stmts DEDENT
10801111
{
1081-
// stmts
1112+
$$ = $3
10821113
}
10831114

10841115
test:

parser/grammar_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ func TestGrammar(t *testing.T) {
196196
{"assert True", "exec", "Module(body=[Assert(test=NameConstant(value=True), msg=None)])"},
197197
{"assert True, 'Bang'", "exec", "Module(body=[Assert(test=NameConstant(value=True), msg=Str(s='Bang'))])"},
198198
{"assert a == b, 'Bang'", "exec", "Module(body=[Assert(test=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), msg=Str(s='Bang'))])"},
199+
{"while True: pass", "exec", "Module(body=[While(test=NameConstant(value=True), body=[Pass()], orelse=[])])"},
200+
{"while True:\n pass\n", "exec", "Module(body=[While(test=NameConstant(value=True), body=[Pass()], orelse=[])])"},
201+
{"while True:\n pass\nelse:\n return\n", "exec", "Module(body=[While(test=NameConstant(value=True), body=[Pass()], orelse=[Return(value=None)])])"},
202+
{"if True: pass", "exec", "Module(body=[If(test=NameConstant(value=True), body=[Pass()], orelse=[])])"},
203+
{"if True:\n pass\n", "exec", "Module(body=[If(test=NameConstant(value=True), body=[Pass()], orelse=[])])"},
204+
{"if True:\n pass\n continue\nelse:\n break\n pass\n", "exec", "Module(body=[If(test=NameConstant(value=True), body=[Pass(), Continue()], orelse=[Break(), Pass()])])"},
205+
{"if a:\n continue\nelif b:\n break\nelif c:\n pass\nelif c:\n continue\n pass\n", "exec", "Module(body=[If(test=Name(id='a', ctx=Load()), body=[Continue()], orelse=[If(test=Name(id='b', ctx=Load()), body=[Break()], orelse=[If(test=Name(id='c', ctx=Load()), body=[Pass()], orelse=[If(test=Name(id='c', ctx=Load()), body=[Continue(), Pass()], orelse=[])])])])])"},
206+
{"if a:\n continue\nelif b:\n break\nelse:\n continue\n pass\n", "exec", "Module(body=[If(test=Name(id='a', ctx=Load()), body=[Continue()], orelse=[If(test=Name(id='b', ctx=Load()), body=[Break()], orelse=[Continue(), Pass()])])])"},
207+
{"if a:\n continue\nelif b:\n break\nelif c:\n pass\nelse:\n continue\n pass\n", "exec", "Module(body=[If(test=Name(id='a', ctx=Load()), body=[Continue()], orelse=[If(test=Name(id='b', ctx=Load()), body=[Break()], orelse=[If(test=Name(id='c', ctx=Load()), body=[Pass()], orelse=[Continue(), Pass()])])])])"},
208+
{"for a in b: pass", "exec", "Module(body=[For(target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[Pass()], orelse=[])])"},
209+
{"for a, b in b: pass", "exec", "Module(body=[For(target=Tuple(elts=[Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store()), iter=Name(id='b', ctx=Load()), body=[Pass()], orelse=[])])"},
210+
{"for a, b in b:\n pass\nelse: break\n", "exec", "Module(body=[For(target=Tuple(elts=[Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store()), iter=Name(id='b', ctx=Load()), body=[Pass()], orelse=[Break()])])"},
199211
// END TESTS
200212
} {
201213
Ast, err := ParseString(test.in, test.mode)

parser/make_grammar_test.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,55 @@
203203
("assert True", "exec"),
204204
("assert True, 'Bang'", "exec"),
205205
("assert a == b, 'Bang'", "exec"),
206+
207+
# Compound statements
208+
("while True: pass", "exec"),
209+
("while True:\n pass\n", "exec"),
210+
("while True:\n pass\nelse:\n return\n", "exec"),
211+
("if True: pass", "exec"),
212+
("if True:\n pass\n", "exec"),
213+
("""\
214+
if True:
215+
pass
216+
continue
217+
else:
218+
break
219+
pass
220+
""", "exec"),
221+
("""\
222+
if a:
223+
continue
224+
elif b:
225+
break
226+
elif c:
227+
pass
228+
elif c:
229+
continue
230+
pass
231+
""", "exec"),
232+
("""\
233+
if a:
234+
continue
235+
elif b:
236+
break
237+
else:
238+
continue
239+
pass
240+
""", "exec"),
241+
("""\
242+
if a:
243+
continue
244+
elif b:
245+
break
246+
elif c:
247+
pass
248+
else:
249+
continue
250+
pass
251+
""", "exec"),
252+
("for a in b: pass", "exec"),
253+
("for a, b in b: pass", "exec"),
254+
("for a, b in b:\n pass\nelse: break\n", "exec"),
206255
]
207256

208257
def dump(source, mode):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy