123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- %{
- package build
- %}
- %union {
-
- tok string
- str string
- pos Position
- triple bool
-
- expr Expr
- exprs []Expr
- forc *ForClause
- ifs []*IfClause
- forifs *ForClauseWithIfClausesOpt
- forsifs []*ForClauseWithIfClausesOpt
- string *StringExpr
- strings []*StringExpr
- block CodeBlock
-
- comma Position
- lastRule Expr
- }
- %token <pos> '%'
- %token <pos> '('
- %token <pos> ')'
- %token <pos> '*'
- %token <pos> '+'
- %token <pos> ','
- %token <pos> '-'
- %token <pos> '.'
- %token <pos> '/'
- %token <pos> ':'
- %token <pos> '<'
- %token <pos> '='
- %token <pos> '>'
- %token <pos> '['
- %token <pos> ']'
- %token <pos> '{'
- %token <pos> '}'
- %token <pos> _AUGM
- %token <pos> _AND
- %token <pos> _COMMENT
- %token <pos> _EOF
- %token <pos> _EQ
- %token <pos> _FOR
- %token <pos> _GE
- %token <pos> _IDENT
- %token <pos> _IF
- %token <pos> _ELSE
- %token <pos> _ELIF
- %token <pos> _IN
- %token <pos> _IS
- %token <pos> _LAMBDA
- %token <pos> _LOAD
- %token <pos> _LE
- %token <pos> _NE
- %token <pos> _NOT
- %token <pos> _OR
- %token <pos> _PYTHON
- %token <pos> _STRING
- %token <pos> _DEF
- %token <pos> _RETURN
- %token <pos> _INDENT
- %token <pos> _UNINDENT
- %type <pos> comma_opt
- %type <expr> expr
- %type <expr> expr_opt
- %type <expr> primary_expr
- %type <exprs> exprs
- %type <exprs> exprs_opt
- %type <exprs> primary_exprs
- %type <forc> for_clause
- %type <forifs> for_clause_with_if_clauses_opt
- %type <forsifs> for_clauses_with_if_clauses_opt
- %type <expr> ident
- %type <ifs> if_clauses_opt
- %type <exprs> stmts
- %type <exprs> stmt
- %type <expr> block_stmt
- %type <expr> if_else_block
- %type <exprs> simple_stmt
- %type <expr> small_stmt
- %type <exprs> small_stmts_continuation
- %type <expr> keyvalue
- %type <exprs> keyvalues
- %type <exprs> keyvalues_no_comma
- %type <string> string
- %type <strings> strings
- %type <block> suite
- %left ShiftInstead
- %left '\n'
- %left _ASSERT
- %left '=' _AUGM
- %left _IF _ELSE _ELIF
- %left ','
- %left ':'
- %left _IN _NOT _IS
- %left _OR
- %left _AND
- %left '<' '>' _EQ _NE _LE _GE
- %left '+' '-'
- %left '*' '/' '%'
- %left '.' '[' '('
- %right _UNARY
- %left _STRING
- %%
- file:
- stmts _EOF
- {
- yylex.(*input).file = &File{Stmt: $1}
- return 0
- }
- suite:
- '\n' _INDENT stmts _UNINDENT
- {
- $$ = CodeBlock{
- Start: $2,
- Statements: $3,
- End: End{Pos: $4},
- }
- }
- | simple_stmt
- {
-
- start, _ := $1[0].Span()
- _, end := $1[len($1)-1].Span()
- $$ = CodeBlock{
- Start: start,
- Statements: $1,
- End: End{Pos: end},
- }
- }
- stmts:
- {
- $$ = nil
- $<lastRule>$ = nil
- }
- | stmts stmt
- {
-
-
- if cb, ok := $<lastRule>1.(*CommentBlock); ok {
- $$ = append($1[:len($1)-1], $2...)
- $2[0].Comment().Before = cb.After
- $<lastRule>$ = $2[len($2)-1]
- break
- }
-
- $$ = append($1, $2...)
- $<lastRule>$ = $2[len($2)-1]
-
-
-
-
-
-
-
-
-
- if x := $<lastRule>1; x != nil {
- com := x.Comment()
-
- $2[0].Comment().Before = com.After
- com.After = nil
- }
- }
- | stmts '\n'
- {
-
- $$ = $1
- $<lastRule>$ = nil
- }
- | stmts _COMMENT '\n'
- {
- $$ = $1
- $<lastRule>$ = $<lastRule>1
- if $<lastRule>$ == nil {
- cb := &CommentBlock{Start: $2}
- $$ = append($$, cb)
- $<lastRule>$ = cb
- }
- com := $<lastRule>$.Comment()
- com.After = append(com.After, Comment{Start: $2, Token: $<tok>2})
- }
- stmt:
- simple_stmt
- {
- $$ = $1
- }
- | block_stmt
- {
- $$ = []Expr{$1}
- }
- block_stmt:
- _DEF _IDENT '(' exprs_opt ')' ':' suite
- {
- $$ = &FuncDef{
- Start: $1,
- Name: $<tok>2,
- ListStart: $3,
- Args: $4,
- Body: $7,
- End: $7.End,
- ForceCompact: forceCompact($3, $4, $5),
- ForceMultiLine: forceMultiLine($3, $4, $5),
- }
- }
- | _FOR primary_exprs _IN expr ':' suite
- {
- $$ = &ForLoop{
- Start: $1,
- LoopVars: $2,
- Iterable: $4,
- Body: $6,
- End: $6.End,
- }
- }
- | if_else_block
- {
- $$ = $1
- }
- if_else_block:
- _IF expr ':' suite
- {
- $$ = &IfElse{
- Start: $1,
- Conditions: []Condition{
- Condition{
- If: $2,
- Then: $4,
- },
- },
- End: $4.End,
- }
- }
- | if_else_block elif expr ':' suite
- {
- block := $1.(*IfElse)
- block.Conditions = append(block.Conditions, Condition{
- If: $3,
- Then: $5,
- })
- block.End = $5.End
- $$ = block
- }
- | if_else_block _ELSE ':' suite
- {
- block := $1.(*IfElse)
- block.Conditions = append(block.Conditions, Condition{
- Then: $4,
- })
- block.End = $4.End
- $$ = block
- }
- elif:
- _ELSE _IF
- | _ELIF
- simple_stmt:
- small_stmt small_stmts_continuation semi_opt '\n'
- {
- $$ = append([]Expr{$1}, $2...)
- $<lastRule>$ = $$[len($$)-1]
- }
- small_stmts_continuation:
- {
- $$ = []Expr{}
- }
- | small_stmts_continuation ';' small_stmt
- {
- $$ = append($1, $3)
- }
- small_stmt:
- expr %prec ShiftInstead
- | _RETURN expr
- {
- _, end := $2.Span()
- $$ = &ReturnExpr{
- X: $2,
- End: end,
- }
- }
- | _RETURN
- {
- $$ = &ReturnExpr{End: $1}
- }
- | _PYTHON
- {
- $$ = &PythonBlock{Start: $1, Token: $<tok>1}
- }
- semi_opt:
- | ';'
- primary_expr:
- ident
- | primary_expr '.' _IDENT
- {
- $$ = &DotExpr{
- X: $1,
- Dot: $2,
- NamePos: $3,
- Name: $<tok>3,
- }
- }
- | _LOAD '(' exprs_opt ')'
- {
- $$ = &CallExpr{
- X: &LiteralExpr{Start: $1, Token: "load"},
- ListStart: $2,
- List: $3,
- End: End{Pos: $4},
- ForceCompact: forceCompact($2, $3, $4),
- ForceMultiLine: forceMultiLine($2, $3, $4),
- }
- }
- | primary_expr '(' exprs_opt ')'
- {
- $$ = &CallExpr{
- X: $1,
- ListStart: $2,
- List: $3,
- End: End{Pos: $4},
- ForceCompact: forceCompact($2, $3, $4),
- ForceMultiLine: forceMultiLine($2, $3, $4),
- }
- }
- | primary_expr '[' expr ']'
- {
- $$ = &IndexExpr{
- X: $1,
- IndexStart: $2,
- Y: $3,
- End: $4,
- }
- }
- | primary_expr '[' expr_opt ':' expr_opt ']'
- {
- $$ = &SliceExpr{
- X: $1,
- SliceStart: $2,
- From: $3,
- FirstColon: $4,
- To: $5,
- End: $6,
- }
- }
- | primary_expr '[' expr_opt ':' expr_opt ':' expr_opt ']'
- {
- $$ = &SliceExpr{
- X: $1,
- SliceStart: $2,
- From: $3,
- FirstColon: $4,
- To: $5,
- SecondColon: $6,
- Step: $7,
- End: $8,
- }
- }
- | primary_expr '(' expr for_clauses_with_if_clauses_opt ')'
- {
- $$ = &CallExpr{
- X: $1,
- ListStart: $2,
- List: []Expr{
- &ListForExpr{
- Brack: "",
- Start: $2,
- X: $3,
- For: $4,
- End: End{Pos: $5},
- },
- },
- End: End{Pos: $5},
- }
- }
- | strings %prec ShiftInstead
- {
- if len($1) == 1 {
- $$ = $1[0]
- break
- }
- $$ = $1[0]
- for _, x := range $1[1:] {
- _, end := $$.Span()
- $$ = binary($$, end, "+", x)
- }
- }
- | '[' exprs_opt ']'
- {
- $$ = &ListExpr{
- Start: $1,
- List: $2,
- Comma: $<comma>2,
- End: End{Pos: $3},
- ForceMultiLine: forceMultiLine($1, $2, $3),
- }
- }
- | '[' expr for_clauses_with_if_clauses_opt ']'
- {
- exprStart, _ := $2.Span()
- $$ = &ListForExpr{
- Brack: "[]",
- Start: $1,
- X: $2,
- For: $3,
- End: End{Pos: $4},
- ForceMultiLine: $1.Line != exprStart.Line,
- }
- }
- | '(' expr for_clauses_with_if_clauses_opt ')'
- {
- exprStart, _ := $2.Span()
- $$ = &ListForExpr{
- Brack: "()",
- Start: $1,
- X: $2,
- For: $3,
- End: End{Pos: $4},
- ForceMultiLine: $1.Line != exprStart.Line,
- }
- }
- | '{' keyvalue for_clauses_with_if_clauses_opt '}'
- {
- exprStart, _ := $2.Span()
- $$ = &ListForExpr{
- Brack: "{}",
- Start: $1,
- X: $2,
- For: $3,
- End: End{Pos: $4},
- ForceMultiLine: $1.Line != exprStart.Line,
- }
- }
- | '{' keyvalues '}'
- {
- $$ = &DictExpr{
- Start: $1,
- List: $2,
- Comma: $<comma>2,
- End: End{Pos: $3},
- ForceMultiLine: forceMultiLine($1, $2, $3),
- }
- }
- | '{' exprs_opt '}'
- {
- $$ = &SetExpr{
- Start: $1,
- List: $2,
- Comma: $<comma>2,
- End: End{Pos: $3},
- ForceMultiLine: forceMultiLine($1, $2, $3),
- }
- }
- | '(' exprs_opt ')'
- {
- if len($2) == 1 && $<comma>2.Line == 0 {
-
- $$ = &ParenExpr{
- Start: $1,
- X: $2[0],
- End: End{Pos: $3},
- ForceMultiLine: forceMultiLine($1, $2, $3),
- }
- } else {
- $$ = &TupleExpr{
- Start: $1,
- List: $2,
- Comma: $<comma>2,
- End: End{Pos: $3},
- ForceCompact: forceCompact($1, $2, $3),
- ForceMultiLine: forceMultiLine($1, $2, $3),
- }
- }
- }
- | '-' primary_expr %prec _UNARY { $$ = unary($1, $<tok>1, $2) }
- expr:
- primary_expr
- | _LAMBDA exprs ':' expr
- {
- $$ = &LambdaExpr{
- Lambda: $1,
- Var: $2,
- Colon: $3,
- Expr: $4,
- }
- }
- | _NOT expr %prec _UNARY { $$ = unary($1, $<tok>1, $2) }
- | '*' expr %prec _UNARY { $$ = unary($1, $<tok>1, $2) }
- | expr '*' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '%' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '/' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '+' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '-' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '<' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '>' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _EQ expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _LE expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _NE expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _GE expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr '=' expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _AUGM expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _IN expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _NOT _IN expr { $$ = binary($1, $2, "not in", $4) }
- | expr _OR expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _AND expr { $$ = binary($1, $2, $<tok>2, $3) }
- | expr _IS expr
- {
- if b, ok := $3.(*UnaryExpr); ok && b.Op == "not" {
- $$ = binary($1, $2, "is not", b.X)
- } else {
- $$ = binary($1, $2, $<tok>2, $3)
- }
- }
- | expr _IF expr _ELSE expr
- {
- $$ = &ConditionalExpr{
- Then: $1,
- IfStart: $2,
- Test: $3,
- ElseStart: $4,
- Else: $5,
- }
- }
- expr_opt:
- {
- $$ = nil
- }
- | expr
- comma_opt:
- {
- $$ = Position{}
- }
- | ','
- keyvalue:
- expr ':' expr {
- $$ = &KeyValueExpr{
- Key: $1,
- Colon: $2,
- Value: $3,
- }
- }
- keyvalues_no_comma:
- keyvalue
- {
- $$ = []Expr{$1}
- }
- | keyvalues_no_comma ',' keyvalue
- {
- $$ = append($1, $3)
- }
- keyvalues:
- keyvalues_no_comma
- {
- $$ = $1
- }
- | keyvalues_no_comma ','
- {
- $$ = $1
- }
- exprs:
- expr
- {
- $$ = []Expr{$1}
- }
- | exprs ',' expr
- {
- $$ = append($1, $3)
- }
- exprs_opt:
- {
- $$, $<comma>$ = nil, Position{}
- }
- | exprs comma_opt
- {
- $$, $<comma>$ = $1, $2
- }
- primary_exprs:
- primary_expr
- {
- $$ = []Expr{$1}
- }
- | primary_exprs ',' primary_expr
- {
- $$ = append($1, $3)
- }
- string:
- _STRING
- {
- $$ = &StringExpr{
- Start: $1,
- Value: $<str>1,
- TripleQuote: $<triple>1,
- End: $1.add($<tok>1),
- Token: $<tok>1,
- }
- }
- strings:
- string
- {
- $$ = []*StringExpr{$1}
- }
- | strings string
- {
- $$ = append($1, $2)
- }
- ident:
- _IDENT
- {
- $$ = &LiteralExpr{Start: $1, Token: $<tok>1}
- }
- for_clause:
- _FOR primary_exprs _IN expr
- {
- $$ = &ForClause{
- For: $1,
- Var: $2,
- In: $3,
- Expr: $4,
- }
- }
- for_clause_with_if_clauses_opt:
- for_clause if_clauses_opt {
- $$ = &ForClauseWithIfClausesOpt{
- For: $1,
- Ifs: $2,
- }
- }
- for_clauses_with_if_clauses_opt:
- for_clause_with_if_clauses_opt
- {
- $$ = []*ForClauseWithIfClausesOpt{$1}
- }
- | for_clauses_with_if_clauses_opt for_clause_with_if_clauses_opt {
- $$ = append($1, $2)
- }
- if_clauses_opt:
- {
- $$ = nil
- }
- | if_clauses_opt _IF expr
- {
- $$ = append($1, &IfClause{
- If: $2,
- Cond: $3,
- })
- }
- %%
- func unary(pos Position, op string, x Expr) Expr {
- return &UnaryExpr{
- OpStart: pos,
- Op: op,
- X: x,
- }
- }
- func binary(x Expr, pos Position, op string, y Expr) Expr {
- _, xend := x.Span()
- ystart, _ := y.Span()
- return &BinaryExpr{
- X: x,
- OpStart: pos,
- Op: op,
- LineBreak: xend.Line < ystart.Line,
- Y: y,
- }
- }
- func isSimpleExpression(expr *Expr) bool {
- switch x := (*expr).(type) {
- case *LiteralExpr, *StringExpr:
- return true
- case *UnaryExpr:
- _, ok := x.X.(*LiteralExpr)
- return ok
- case *ListExpr:
- return len(x.List) == 0
- case *TupleExpr:
- return len(x.List) == 0
- case *DictExpr:
- return len(x.List) == 0
- case *SetExpr:
- return len(x.List) == 0
- default:
- return false
- }
- }
- func forceCompact(start Position, list []Expr, end Position) bool {
- if len(list) <= 1 {
-
- return false
- }
-
-
- line := start.Line
- for _, x := range list {
- start, end := x.Span()
- if start.Line != line {
- return false
- }
- line = end.Line
- if !isSimpleExpression(&x) {
- return false
- }
- }
- return end.Line == line
- }
- func forceMultiLine(start Position, list []Expr, end Position) bool {
- if len(list) > 1 {
-
- return false
- }
- if len(list) == 0 {
-
- return start.Line != end.Line
- }
-
-
-
- elemStart, elemEnd := list[0].Span()
- return start.Line != elemStart.Line || end.Line != elemEnd.Line
- }
|