Skip to content

Commit 133ce36

Browse files
committed
trailers - call and subscript - call not finished
1 parent 6305d51 commit 133ce36

File tree

5 files changed

+135
-13
lines changed

5 files changed

+135
-13
lines changed

ast/ast.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ type Slice struct {
623623

624624
type ExtSlice struct {
625625
SliceBase
626-
Dims []Slice
626+
Dims []Slicer
627627
}
628628

629629
type Index struct {

ast/dump.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func dump(ast interface{}, name string) string {
4343
fieldType := astType.Field(i)
4444
fieldValue := astValue.Field(i)
4545
fname := strings.ToLower(fieldType.Name)
46-
if fname == "stmtbase" || fname == "exprbase" || fname == "modbase" {
46+
if fname == "stmtbase" || fname == "exprbase" || fname == "modbase" || fname == "slicebase" {
4747
continue
4848
}
4949
if fieldValue.Kind() == reflect.Slice && fieldValue.Type().Elem().Kind() != reflect.Uint8 {

parser/grammar.y

+91-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package parser
55
// Grammar for Python
66

77
import (
8+
"fmt"
89
"github.com/ncw/gpython/py"
910
"github.com/ncw/gpython/ast"
1011
)
@@ -21,6 +22,26 @@ func tupleOrExpr(pos ast.Pos, elts []ast.Expr, optional_comma bool) ast.Expr {
2122
}
2223
}
2324

25+
// Apply trailers (if any) to expr
26+
//
27+
// trailers are half made Call, Subscript or Attribute
28+
func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr {
29+
//trailers := $1
30+
for _, trailer := range trailers {
31+
switch x := trailer.(type) {
32+
case *ast.Call:
33+
x.Func, expr = expr, x
34+
case *ast.Subscript:
35+
x.Value, expr = expr, x
36+
case *ast.Attribute:
37+
x.Value, expr = expr, x
38+
default:
39+
panic(fmt.Sprintf("Unknown trailer type: %T", expr))
40+
}
41+
}
42+
return expr
43+
}
44+
2445
%}
2546

2647
%union {
@@ -37,18 +58,20 @@ func tupleOrExpr(pos ast.Pos, elts []ast.Expr, optional_comma bool) ast.Expr {
3758
comma bool
3859
comprehensions []ast.Comprehension
3960
isExpr bool
61+
slice ast.Slicer
4062
}
4163

4264
%type <obj> strings
4365
%type <mod> inputs file_input single_input eval_input
4466
%type <stmts> simple_stmt stmt nl_or_stmt small_stmts stmts
4567
%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
4668
%type <op> augassign
47-
%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
69+
%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
4870
%type <exprs> exprlist testlistraw comp_if comp_iter expr_or_star_exprs test_or_star_exprs tests test_colon_tests trailers
4971
%type <cmpop> comp_op
5072
%type <comma> optional_comma
5173
%type <comprehensions> comp_for
74+
%type <slice> subscript subscriptlist subscripts
5275

5376
%token NEWLINE
5477
%token ENDMARKER
@@ -994,13 +1017,11 @@ factor:
9941017
power:
9951018
atom trailers
9961019
{
997-
// FIXME apply trailers (if any) to atom
998-
$$ = $1
1020+
$$ = applyTrailers($1, $2)
9991021
}
10001022
| atom trailers STARSTAR factor
10011023
{
1002-
// FIXME apply trailers (if any) to atom
1003-
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: $1, Op: ast.Pow, Right: $4}
1024+
$$ = &ast.BinOp{ExprBase: ast.ExprBase{$<pos>$}, Left: applyTrailers($1, $2), Op: ast.Pow, Right: $4}
10041025
}
10051026

10061027
// Trailers are half made Call, Attribute or Subscript
@@ -1117,51 +1138,110 @@ atom:
11171138
trailer:
11181139
'(' ')'
11191140
{
1120-
// FIXME
1141+
$$ = &ast.Call{ExprBase: ast.ExprBase{$<pos>$}}
11211142
}
11221143
| '(' arglist ')'
11231144
{
11241145
// FIXME
1146+
$$ = nil
11251147
}
11261148
| '[' subscriptlist ']'
11271149
{
1128-
// FIXME
1150+
slice := $2
1151+
// If all items of a ExtSlice are just Index then return as tuple
1152+
if extslice, ok := slice.(*ast.ExtSlice); ok {
1153+
elts := make([]ast.Expr, len(extslice.Dims))
1154+
for i, item := range(extslice.Dims) {
1155+
if index, isIndex := item.(*ast.Index); isIndex {
1156+
elts[i] = index.Value
1157+
} else {
1158+
goto notAllIndex
1159+
}
1160+
}
1161+
slice = &ast.Index{SliceBase: extslice.SliceBase, Value: &ast.Tuple{ExprBase: ast.ExprBase{extslice.SliceBase.Pos}, Elts: elts, Ctx: ast.Load}}
1162+
notAllIndex:
1163+
}
1164+
$$ = &ast.Subscript{ExprBase: ast.ExprBase{$<pos>$}, Slice: slice, Ctx: ast.Load}
11291165
}
11301166
| '.' NAME
11311167
{
1132-
$$ = &ast.Attribute{ExprBase: ast.ExprBase{$<pos>$}, Attr: ast.Identifier($2)} // FIXME Ctx
1168+
$$ = &ast.Attribute{ExprBase: ast.ExprBase{$<pos>$}, Attr: ast.Identifier($2), Ctx: ast.Load}
11331169
}
11341170

11351171
subscripts:
11361172
subscript
11371173
{
1138-
// FIXME
1174+
$$ = $1
1175+
$<isExpr>$ = true
11391176
}
11401177
| subscripts ',' subscript
11411178
{
1142-
// FIXME
1179+
if !$<isExpr>1 {
1180+
extSlice := $$.(*ast.ExtSlice)
1181+
extSlice.Dims = append(extSlice.Dims, $3)
1182+
} else {
1183+
$$ = &ast.ExtSlice{SliceBase: ast.SliceBase{$<pos>$}, Dims: []ast.Slicer{$1, $3}}
1184+
}
1185+
$<isExpr>$ = false
11431186
}
11441187

11451188
subscriptlist:
11461189
subscripts optional_comma
11471190
{
1148-
// FIXME
1191+
if $2 && $<isExpr>1 {
1192+
$$ = &ast.ExtSlice{SliceBase: ast.SliceBase{$<pos>$}, Dims: []ast.Slicer{$1}}
1193+
} else {
1194+
$$ = $1
1195+
}
11491196
}
11501197

11511198
subscript:
11521199
test
1200+
{
1201+
$$ = &ast.Index{SliceBase: ast.SliceBase{$<pos>$}, Value: $1}
1202+
}
11531203
| ':'
1204+
{
1205+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: nil, Upper: nil, Step: nil}
1206+
}
11541207
| ':' sliceop
1208+
{
1209+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: nil, Upper: nil, Step: $2}
1210+
}
11551211
| ':' test
1212+
{
1213+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: nil, Upper: $2, Step: nil}
1214+
}
11561215
| ':' test sliceop
1216+
{
1217+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: nil, Upper: $2, Step: $3}
1218+
}
11571219
| test ':'
1220+
{
1221+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: $1, Upper: nil, Step: nil}
1222+
}
11581223
| test ':' sliceop
1224+
{
1225+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: $1, Upper: nil, Step: $3}
1226+
}
11591227
| test ':' test
1228+
{
1229+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: $1, Upper: $3, Step: nil}
1230+
}
11601231
| test ':' test sliceop
1232+
{
1233+
$$ = &ast.Slice{SliceBase: ast.SliceBase{$<pos>$}, Lower: $1, Upper: $3, Step: $4}
1234+
}
11611235

11621236
sliceop:
11631237
':'
1238+
{
1239+
$$ = nil
1240+
}
11641241
| ':' test
1242+
{
1243+
$$ = $2
1244+
}
11651245

11661246
expr_or_star_expr:
11671247
expr

parser/grammar_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,26 @@ func TestGrammar(t *testing.T) {
130130
{"(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())]))"},
131131
{"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())])]))"},
132132
{"(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())]))"},
133+
{"a()", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None))"},
134+
{"a.b", "eval", "Expression(body=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()))"},
135+
{"a.b.c.d", "eval", "Expression(body=Attribute(value=Attribute(value=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()), attr='c', ctx=Load()), attr='d', ctx=Load()))"},
136+
{"a.b().c.d()()", "eval", "Expression(body=Call(func=Call(func=Attribute(value=Attribute(value=Call(func=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None), attr='c', ctx=Load()), attr='d', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None), args=[], keywords=[], starargs=None, kwargs=None))"},
137+
{"x[a]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Index(value=Name(id='a', ctx=Load())), ctx=Load()))"},
138+
{"x[a:b]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=Name(id='a', ctx=Load()), upper=Name(id='b', ctx=Load()), step=None), ctx=Load()))"},
139+
{"x[a:b:c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=Name(id='a', ctx=Load()), upper=Name(id='b', ctx=Load()), step=Name(id='c', ctx=Load())), ctx=Load()))"},
140+
{"x[:b:c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=None, upper=Name(id='b', ctx=Load()), step=Name(id='c', ctx=Load())), ctx=Load()))"},
141+
{"x[a::c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=Name(id='a', ctx=Load()), upper=None, step=Name(id='c', ctx=Load())), ctx=Load()))"},
142+
{"x[a:b:]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=Name(id='a', ctx=Load()), upper=Name(id='b', ctx=Load()), step=None), ctx=Load()))"},
143+
{"x[::c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=None, upper=None, step=Name(id='c', ctx=Load())), ctx=Load()))"},
144+
{"x[:b:]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=None, upper=Name(id='b', ctx=Load()), step=None), ctx=Load()))"},
145+
{"x[::c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=None, upper=None, step=Name(id='c', ctx=Load())), ctx=Load()))"},
146+
{"x[::]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Slice(lower=None, upper=None, step=None), ctx=Load()))"},
147+
{"x[a,p]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Index(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='p', ctx=Load())], ctx=Load())), ctx=Load()))"},
148+
{"x[a, b]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Index(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())], ctx=Load())), ctx=Load()))"},
149+
{"x[a, b, c]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=Index(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load()), Name(id='c', ctx=Load())], ctx=Load())), ctx=Load()))"},
150+
{"x[a, b:c, ::d]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Name(id='a', ctx=Load())), Slice(lower=Name(id='b', ctx=Load()), upper=Name(id='c', ctx=Load()), step=None), Slice(lower=None, upper=None, step=Name(id='d', ctx=Load()))]), ctx=Load()))"},
151+
{"x[a, b:c, ::d]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Name(id='a', ctx=Load())), Slice(lower=Name(id='b', ctx=Load()), upper=Name(id='c', ctx=Load()), step=None), Slice(lower=None, upper=None, step=Name(id='d', ctx=Load()))]), ctx=Load()))"},
152+
{"x[0, 1:2, ::5, ...]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Num(n=0)), Slice(lower=Num(n=1), upper=Num(n=2), step=None), Slice(lower=None, upper=None, step=Num(n=5)), Index(value=Ellipsis())]), ctx=Load()))"},
133153
// END TESTS
134154
} {
135155
Ast, err := ParseString(test.in, test.mode)

parser/make_grammar_test.py

+22
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,28 @@
132132
("a==(b<c)", "eval"),
133133
("(a==b)<(c>d)>e", "eval"),
134134

135+
# trailers
136+
("a()", "eval"),
137+
("a.b", "eval"),
138+
("a.b.c.d", "eval"),
139+
("a.b().c.d()()", "eval"),
140+
("x[a]", "eval"),
141+
("x[a:b]", "eval"),
142+
("x[a:b:c]", "eval"),
143+
("x[:b:c]", "eval"),
144+
("x[a::c]", "eval"),
145+
("x[a:b:]", "eval"),
146+
("x[::c]", "eval"),
147+
("x[:b:]", "eval"),
148+
("x[::c]", "eval"),
149+
("x[::]", "eval"),
150+
("x[a,p]", "eval"),
151+
("x[a, b]", "eval"),
152+
("x[a, b, c]", "eval"),
153+
("x[a, b:c, ::d]", "eval"),
154+
("x[a, b:c, ::d]", "eval"),
155+
("x[0, 1:2, ::5, ...]", "eval"),
156+
135157
# ("del a,b", "exec"),
136158
]
137159

0 commit comments

Comments
 (0)