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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 91 additions & 11 deletions
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

Lines changed: 20 additions & 0 deletions
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

Lines changed: 22 additions & 0 deletions
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)
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