Skip to content

Commit 216cff9

Browse files
committed
BinOp, BoolOp and UnaryOp
1 parent 058dc76 commit 216cff9

File tree

4 files changed

+129
-21
lines changed

4 files changed

+129
-21
lines changed

ast/dump.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ func Dump(ast Ast) string {
6767
return "<nil>"
6868
}
6969
name := ast.Type().Name
70-
if name == "ExprStmt" {
70+
switch name {
71+
case "ExprStmt":
7172
name = "Expr"
7273
}
7374
return dump(ast, name)

parser/grammar.y

+30-20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func tupleOrExpr(pos ast.Pos, elts []ast.Expr, optional_comma bool) ast.Expr {
3636
cmpop ast.CmpOp
3737
comma bool
3838
comprehensions []ast.Comprehension
39+
isExpr bool
3940
}
4041

4142
%type <obj> strings
@@ -780,34 +781,40 @@ or_test:
780781
and_test
781782
{
782783
$$ = $1
784+
$<isExpr>$ = true
783785
}
784786
| or_test OR and_test
785787
{
786-
if boolop, ok := $$.(*ast.BoolOp); ok && boolop.Op == ast.Or {
788+
if !$<isExpr>1 {
789+
boolop := $$.(*ast.BoolOp)
787790
boolop.Values = append(boolop.Values, $3)
788791
} else {
789792
$$ = &ast.BoolOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.Or, Values: []ast.Expr{$$, $3}} // FIXME Ctx
790793
}
794+
$<isExpr>$ = false
791795
}
792796

793797
and_test:
794798
not_test
795799
{
796800
$$ = $1
801+
$<isExpr>$ = true
797802
}
798803
| and_test AND not_test
799804
{
800-
if boolop, ok := $$.(*ast.BoolOp); ok && boolop.Op == ast.And {
805+
if !$<isExpr>1 {
806+
boolop := $$.(*ast.BoolOp)
801807
boolop.Values = append(boolop.Values, $3)
802808
} else {
803809
$$ = &ast.BoolOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.And, Values: []ast.Expr{$$, $3}} // FIXME Ctx
804810
}
811+
$<isExpr>$ = false
805812
}
806813

807814
not_test:
808815
NOT not_test
809816
{
810-
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.Not, Operand: $$} // FIXME Ctx
817+
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.Not, Operand: $2}
811818
}
812819
| comparison
813820
{
@@ -818,15 +825,18 @@ comparison:
818825
expr
819826
{
820827
$$ = $1
828+
$<isExpr>$ = true
821829
}
822830
| comparison comp_op expr
823831
{
824-
if comp, ok := $$.(*ast.Compare); ok {
832+
if !$<isExpr>1 {
833+
comp := $$.(*ast.Compare)
825834
comp.Ops = append(comp.Ops, $2)
826835
comp.Comparators = append(comp.Comparators, $3)
827836
} else{
828-
comp = &ast.Compare{ExprBase: ast.ExprBase{$<pos>$}, Left: $$, Ops: []ast.CmpOp{$2}, Comparators: []ast.Expr{$3}} // FIXME Ctx
837+
$$ = &ast.Compare{ExprBase: ast.ExprBase{$<pos>$}, Left: $$, Ops: []ast.CmpOp{$2}, Comparators: []ast.Expr{$3}}
829838
}
839+
$<isExpr>$ = false
830840
}
831841

832842
// <> LTGT isn't actually a valid comparison operator in Python. It's here for the
@@ -890,7 +900,7 @@ expr:
890900
}
891901
| expr '|' xor_expr
892902
{
893-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitOr, Right: $3} // FIXME Ctx
903+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitOr, Right: $3}
894904
}
895905

896906
xor_expr:
@@ -900,7 +910,7 @@ xor_expr:
900910
}
901911
| xor_expr '^' and_expr
902912
{
903-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitXor, Right: $3} // FIXME Ctx
913+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitXor, Right: $3}
904914
}
905915

906916
and_expr:
@@ -910,7 +920,7 @@ and_expr:
910920
}
911921
| and_expr '&' shift_expr
912922
{
913-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitAnd, Right: $3} // FIXME Ctx
923+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.BitAnd, Right: $3}
914924
}
915925

916926
shift_expr:
@@ -920,11 +930,11 @@ shift_expr:
920930
}
921931
| shift_expr LTLT arith_expr
922932
{
923-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.LShift, Right: $3} // FIXME Ctx
933+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.LShift, Right: $3}
924934
}
925935
| shift_expr GTGT arith_expr
926936
{
927-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.RShift, Right: $3} // FIXME Ctx
937+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.RShift, Right: $3}
928938
}
929939

930940
arith_expr:
@@ -934,11 +944,11 @@ arith_expr:
934944
}
935945
| arith_expr '+' term
936946
{
937-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Add, Right: $3} // FIXME Ctx
947+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Add, Right: $3}
938948
}
939949
| arith_expr '-' term
940950
{
941-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Sub, Right: $3} // FIXME Ctx
951+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Sub, Right: $3}
942952
}
943953

944954
term:
@@ -948,33 +958,33 @@ term:
948958
}
949959
| term '*' factor
950960
{
951-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Mult, Right: $3} // FIXME Ctx
961+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Mult, Right: $3}
952962
}
953963
| term '/' factor
954964
{
955-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Div, Right: $3} // FIXME Ctx
965+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Div, Right: $3}
956966
}
957967
| term '%' factor
958968
{
959-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Modulo, Right: $3} // FIXME Ctx
969+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Modulo, Right: $3}
960970
}
961971
| term DIVDIV factor
962972
{
963-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.FloorDiv, Right: $3} // FIXME Ctx
973+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.FloorDiv, Right: $3}
964974
}
965975

966976
factor:
967977
'+' factor
968978
{
969-
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.UAdd, Operand: $2} // FIXME Ctx
979+
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.UAdd, Operand: $2}
970980
}
971981
| '-' factor
972982
{
973-
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.USub, Operand: $2} // FIXME Ctx
983+
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.USub, Operand: $2}
974984
}
975985
| '~' factor
976986
{
977-
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.Invert, Operand: $2} // FIXME Ctx
987+
$$ = &ast.UnaryOp{ExprBase: ast.ExprBase{$<pos>$}, Op: ast.Invert, Operand: $2}
978988
}
979989
| power
980990
{
@@ -990,7 +1000,7 @@ power:
9901000
| atom trailers STARSTAR factor
9911001
{
9921002
// FIXME apply trailers (if any) to atom
993-
$$ = $1
1003+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Pow, Right: $4}
9941004
}
9951005

9961006
// Trailers are half made Call, Attribute or Subscript

parser/grammar_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,49 @@ func TestGrammar(t *testing.T) {
8787
{"{ a:b for a in ab if a if b if c }", "eval", "Expression(body=DictComp(key=Name(id='a', ctx=Load()), value=Name(id='b', ctx=Load()), generators=[comprehension(target=Name(id='a', ctx=Store()), iter=Name(id='ab', ctx=Load()), ifs=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load()), Name(id='c', ctx=Load())])]))"},
8888
{"{ a:b for a in ab for A in AB }", "eval", "Expression(body=DictComp(key=Name(id='a', ctx=Load()), value=Name(id='b', ctx=Load()), generators=[comprehension(target=Name(id='a', ctx=Store()), iter=Name(id='ab', ctx=Load()), ifs=[]), comprehension(target=Name(id='A', ctx=Store()), iter=Name(id='AB', ctx=Load()), ifs=[])]))"},
8989
{"{ a:b for a in ab if a if b for A in AB if c }", "eval", "Expression(body=DictComp(key=Name(id='a', ctx=Load()), value=Name(id='b', ctx=Load()), generators=[comprehension(target=Name(id='a', ctx=Store()), iter=Name(id='ab', ctx=Load()), ifs=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())]), comprehension(target=Name(id='A', ctx=Store()), iter=Name(id='AB', ctx=Load()), ifs=[Name(id='c', ctx=Load())])]))"},
90+
{"a|b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=BitOr(), right=Name(id='b', ctx=Load())))"},
91+
{"a^b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=BitXor(), right=Name(id='b', ctx=Load())))"},
92+
{"a&b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=BitAnd(), right=Name(id='b', ctx=Load())))"},
93+
{"a<<b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=LShift(), right=Name(id='b', ctx=Load())))"},
94+
{"a>>b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=RShift(), right=Name(id='b', ctx=Load())))"},
95+
{"a+b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())))"},
96+
{"a-b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Sub(), right=Name(id='b', ctx=Load())))"},
97+
{"a*b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Mult(), right=Name(id='b', ctx=Load())))"},
98+
{"a/b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Div(), right=Name(id='b', ctx=Load())))"},
99+
{"a//b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=FloorDiv(), right=Name(id='b', ctx=Load())))"},
100+
{"a**b", "eval", "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Pow(), right=Name(id='b', ctx=Load())))"},
101+
{"not a", "eval", "Expression(body=UnaryOp(op=Not(), operand=Name(id='a', ctx=Load())))"},
102+
{"+a", "eval", "Expression(body=UnaryOp(op=UAdd(), operand=Name(id='a', ctx=Load())))"},
103+
{"-a", "eval", "Expression(body=UnaryOp(op=USub(), operand=Name(id='a', ctx=Load())))"},
104+
{"~a", "eval", "Expression(body=UnaryOp(op=Invert(), operand=Name(id='a', ctx=Load())))"},
105+
{"a and b", "eval", "Expression(body=BoolOp(op=And(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())]))"},
106+
{"a or b", "eval", "Expression(body=BoolOp(op=Or(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())]))"},
107+
{"a or b or c", "eval", "Expression(body=BoolOp(op=Or(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load()), Name(id='c', ctx=Load())]))"},
108+
{"(a or b) or c", "eval", "Expression(body=BoolOp(op=Or(), values=[BoolOp(op=Or(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())]), Name(id='c', ctx=Load())]))"},
109+
{"a or (b or c)", "eval", "Expression(body=BoolOp(op=Or(), values=[Name(id='a', ctx=Load()), BoolOp(op=Or(), values=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load())])]))"},
110+
{"a and b and c", "eval", "Expression(body=BoolOp(op=And(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load()), Name(id='c', ctx=Load())]))"},
111+
{"(a and b) and c", "eval", "Expression(body=BoolOp(op=And(), values=[BoolOp(op=And(), values=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())]), Name(id='c', ctx=Load())]))"},
112+
{"a and (b and c)", "eval", "Expression(body=BoolOp(op=And(), values=[Name(id='a', ctx=Load()), BoolOp(op=And(), values=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load())])]))"},
113+
{"a+b-c/d", "eval", "Expression(body=BinOp(left=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())), op=Sub(), right=BinOp(left=Name(id='c', ctx=Load()), op=Div(), right=Name(id='d', ctx=Load()))))"},
114+
{"a+b-c/d//e", "eval", "Expression(body=BinOp(left=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())), op=Sub(), right=BinOp(left=BinOp(left=Name(id='c', ctx=Load()), op=Div(), right=Name(id='d', ctx=Load())), op=FloorDiv(), right=Name(id='e', ctx=Load()))))"},
115+
{"a+b-c/d//e%f", "eval", "Expression(body=BinOp(left=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())), op=Sub(), right=BinOp(left=BinOp(left=BinOp(left=Name(id='c', ctx=Load()), op=Div(), right=Name(id='d', ctx=Load())), op=FloorDiv(), right=Name(id='e', ctx=Load())), op=Mod(), right=Name(id='f', ctx=Load()))))"},
116+
{"a+b-c/d//e%f**g", "eval", "Expression(body=BinOp(left=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())), op=Sub(), right=BinOp(left=BinOp(left=BinOp(left=Name(id='c', ctx=Load()), op=Div(), right=Name(id='d', ctx=Load())), op=FloorDiv(), right=Name(id='e', ctx=Load())), op=Mod(), right=BinOp(left=Name(id='f', ctx=Load()), op=Pow(), right=Name(id='g', ctx=Load())))))"},
117+
{"a+b-c/d//e%f**g|h&i^k<<l>>m", "eval", "Expression(body=BinOp(left=BinOp(left=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Name(id='b', ctx=Load())), op=Sub(), right=BinOp(left=BinOp(left=BinOp(left=Name(id='c', ctx=Load()), op=Div(), right=Name(id='d', ctx=Load())), op=FloorDiv(), right=Name(id='e', ctx=Load())), op=Mod(), right=BinOp(left=Name(id='f', ctx=Load()), op=Pow(), right=Name(id='g', ctx=Load())))), op=BitOr(), right=BinOp(left=BinOp(left=Name(id='h', ctx=Load()), op=BitAnd(), right=Name(id='i', ctx=Load())), op=BitXor(), right=BinOp(left=BinOp(left=Name(id='k', ctx=Load()), op=LShift(), right=Name(id='l', ctx=Load())), op=RShift(), right=Name(id='m', ctx=Load())))))"},
118+
{"a==b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]))"},
119+
{"a!=b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[NotEq()], comparators=[Name(id='b', ctx=Load())]))"},
120+
{"a<b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Lt()], comparators=[Name(id='b', ctx=Load())]))"},
121+
{"a<=b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[LtE()], comparators=[Name(id='b', ctx=Load())]))"},
122+
{"a>b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Gt()], comparators=[Name(id='b', ctx=Load())]))"},
123+
{"a>=b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[GtE()], comparators=[Name(id='b', ctx=Load())]))"},
124+
{"a is b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Is()], comparators=[Name(id='b', ctx=Load())]))"},
125+
{"a is not b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[IsNot()], comparators=[Name(id='b', ctx=Load())]))"},
126+
{"a in b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[In()], comparators=[Name(id='b', ctx=Load())]))"},
127+
{"a not in b", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[NotIn()], comparators=[Name(id='b', ctx=Load())]))"},
128+
{"a<b<c<d", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Lt(), Lt(), Lt()], comparators=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load()), Name(id='d', ctx=Load())]))"},
129+
{"a==b<c>d", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Eq(), Lt(), Gt()], comparators=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load()), Name(id='d', ctx=Load())]))"},
130+
{"(a==b)<c", "eval", "Expression(body=Compare(left=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), ops=[Lt()], comparators=[Name(id='c', ctx=Load())]))"},
131+
{"a==(b<c)", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Compare(left=Name(id='b', ctx=Load()), ops=[Lt()], comparators=[Name(id='c', ctx=Load())])]))"},
132+
{"(a==b)<(c>d)>e", "eval", "Expression(body=Compare(left=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), ops=[Lt(), Gt()], comparators=[Compare(left=Name(id='c', ctx=Load()), ops=[Gt()], comparators=[Name(id='d', ctx=Load())]), Name(id='e', ctx=Load())]))"},
90133
// END TESTS
91134
} {
92135
Ast, err := ParseString(test.in, test.mode)

parser/make_grammar_test.py

+54
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
("[1,]", "eval"),
4747
("[1,2]", "eval"),
4848
("[1,2,]", "eval"),
49+
4950
("( a for a in ab )", "eval"),
5051
("( a for a, in ab )", "eval"),
5152
("( a for a, b in ab )", "eval"),
@@ -78,6 +79,59 @@
7879
("{ a:b for a in ab for A in AB }", "eval"),
7980
("{ a:b for a in ab if a if b for A in AB if c }", "eval"),
8081

82+
# BinOp
83+
("a|b", "eval"),
84+
("a^b", "eval"),
85+
("a&b", "eval"),
86+
("a<<b", "eval"),
87+
("a>>b", "eval"),
88+
("a+b", "eval"),
89+
("a-b", "eval"),
90+
("a*b", "eval"),
91+
("a/b", "eval"),
92+
("a//b", "eval"),
93+
("a**b", "eval"),
94+
95+
# UnaryOp
96+
("not a", "eval"),
97+
("+a", "eval"),
98+
("-a", "eval"),
99+
("~a", "eval"),
100+
101+
# BoolOp
102+
("a and b", "eval"),
103+
("a or b", "eval"),
104+
("a or b or c", "eval"),
105+
("(a or b) or c", "eval"),
106+
("a or (b or c)", "eval"),
107+
("a and b and c", "eval"),
108+
("(a and b) and c", "eval"),
109+
("a and (b and c)", "eval"),
110+
111+
# Exprs
112+
("a+b-c/d", "eval"),
113+
("a+b-c/d//e", "eval"),
114+
("a+b-c/d//e%f", "eval"),
115+
("a+b-c/d//e%f**g", "eval"),
116+
("a+b-c/d//e%f**g|h&i^k<<l>>m", "eval"),
117+
118+
("a==b", "eval"),
119+
("a!=b", "eval"),
120+
("a<b", "eval"),
121+
("a<=b", "eval"),
122+
("a>b", "eval"),
123+
("a>=b", "eval"),
124+
("a is b", "eval"),
125+
("a is not b", "eval"),
126+
("a in b", "eval"),
127+
("a not in b", "eval"),
128+
129+
("a<b<c<d", "eval"),
130+
("a==b<c>d", "eval"),
131+
("(a==b)<c", "eval"),
132+
("a==(b<c)", "eval"),
133+
("(a==b)<(c>d)>e", "eval"),
134+
81135
# ("del a,b", "exec"),
82136
]
83137

0 commit comments

Comments
 (0)