github.com/guardangely/gopher-lua@v0.0.0-20200324075529-f92e6f279f59/parse/parser.go.y (about)

     1  %{
     2  package parse
     3  
     4  import (
     5    "github.com/guardangely/gopher-lua/ast"
     6  )
     7  %}
     8  %type<stmts> chunk
     9  %type<stmts> chunk1
    10  %type<stmts> block
    11  %type<stmt>  stat
    12  %type<stmts> elseifs
    13  %type<stmt>  laststat
    14  %type<funcname> funcname
    15  %type<funcname> funcname1
    16  %type<exprlist> varlist
    17  %type<expr> var
    18  %type<namelist> namelist
    19  %type<exprlist> exprlist
    20  %type<expr> expr
    21  %type<expr> string
    22  %type<expr> prefixexp
    23  %type<expr> functioncall
    24  %type<expr> afunctioncall
    25  %type<exprlist> args
    26  %type<expr> function
    27  %type<funcexpr> funcbody
    28  %type<parlist> parlist
    29  %type<expr> tableconstructor
    30  %type<fieldlist> fieldlist
    31  %type<field> field
    32  %type<fieldsep> fieldsep
    33  
    34  %union {
    35    token  ast.Token
    36  
    37    stmts    []ast.Stmt
    38    stmt     ast.Stmt
    39  
    40    funcname *ast.FuncName
    41    funcexpr *ast.FunctionExpr
    42  
    43    exprlist []ast.Expr
    44    expr   ast.Expr
    45  
    46    fieldlist []*ast.Field
    47    field     *ast.Field
    48    fieldsep  string
    49  
    50    namelist []string
    51    parlist  *ast.ParList
    52  }
    53  
    54  /* Reserved words */
    55  %token<token> TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile 
    56  
    57  /* Literals */
    58  %token<token> TEqeq TNeq TLte TGte T2Comma T3Comma TIdent TNumber TString '{' '('
    59  
    60  /* Operators */
    61  %left TOr
    62  %left TAnd
    63  %left '>' '<' TGte TLte TEqeq TNeq
    64  %right T2Comma
    65  %left '+' '-'
    66  %left '*' '/' '%'
    67  %right UNARY /* not # -(unary) */
    68  %right '^'
    69  
    70  %%
    71  
    72  chunk: 
    73          chunk1 {
    74              $$ = $1
    75              if l, ok := yylex.(*Lexer); ok {
    76                  l.Stmts = $$
    77              }
    78          } |
    79          chunk1 laststat {
    80              $$ = append($1, $2)
    81              if l, ok := yylex.(*Lexer); ok {
    82                  l.Stmts = $$
    83              }
    84          } | 
    85          chunk1 laststat ';' {
    86              $$ = append($1, $2)
    87              if l, ok := yylex.(*Lexer); ok {
    88                  l.Stmts = $$
    89              }
    90          }
    91  
    92  chunk1: 
    93          {
    94              $$ = []ast.Stmt{}
    95          } |
    96          chunk1 stat {
    97              $$ = append($1, $2)
    98          } | 
    99          chunk1 ';' {
   100              $$ = $1
   101          }
   102  
   103  block: 
   104          chunk {
   105              $$ = $1
   106          }
   107  
   108  stat:
   109          varlist '=' exprlist {
   110              $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3}
   111              $$.SetLine($1[0].Line())
   112          } |
   113          /* 'stat = functioncal' causes a reduce/reduce conflict */
   114          prefixexp {
   115              if _, ok := $1.(*ast.FuncCallExpr); !ok {
   116                 yylex.(*Lexer).Error("parse error")
   117              } else {
   118                $$ = &ast.FuncCallStmt{Expr: $1}
   119                $$.SetLine($1.Line())
   120              }
   121          } |
   122          TDo block TEnd {
   123              $$ = &ast.DoBlockStmt{Stmts: $2}
   124              $$.SetLine($1.Pos.Line)
   125              $$.SetLastLine($3.Pos.Line)
   126          } |
   127          TWhile expr TDo block TEnd {
   128              $$ = &ast.WhileStmt{Condition: $2, Stmts: $4}
   129              $$.SetLine($1.Pos.Line)
   130              $$.SetLastLine($5.Pos.Line)
   131          } |
   132          TRepeat block TUntil expr {
   133              $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2}
   134              $$.SetLine($1.Pos.Line)
   135              $$.SetLastLine($4.Line())
   136          } |
   137          TIf expr TThen block elseifs TEnd {
   138              $$ = &ast.IfStmt{Condition: $2, Then: $4}
   139              cur := $$
   140              for _, elseif := range $5 {
   141                  cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
   142                  cur = elseif
   143              }
   144              $$.SetLine($1.Pos.Line)
   145              $$.SetLastLine($6.Pos.Line)
   146          } |
   147          TIf expr TThen block elseifs TElse block TEnd {
   148              $$ = &ast.IfStmt{Condition: $2, Then: $4}
   149              cur := $$
   150              for _, elseif := range $5 {
   151                  cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
   152                  cur = elseif
   153              }
   154              cur.(*ast.IfStmt).Else = $7
   155              $$.SetLine($1.Pos.Line)
   156              $$.SetLastLine($8.Pos.Line)
   157          } |
   158          TFor TIdent '=' expr ',' expr TDo block TEnd {
   159              $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8}
   160              $$.SetLine($1.Pos.Line)
   161              $$.SetLastLine($9.Pos.Line)
   162          } |
   163          TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd {
   164              $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10}
   165              $$.SetLine($1.Pos.Line)
   166              $$.SetLastLine($11.Pos.Line)
   167          } |
   168          TFor namelist TIn exprlist TDo block TEnd {
   169              $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6}
   170              $$.SetLine($1.Pos.Line)
   171              $$.SetLastLine($7.Pos.Line)
   172          } |
   173          TFunction funcname funcbody {
   174              $$ = &ast.FuncDefStmt{Name: $2, Func: $3}
   175              $$.SetLine($1.Pos.Line)
   176              $$.SetLastLine($3.LastLine())
   177          } |
   178          TLocal TFunction TIdent funcbody {
   179              $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}}
   180              $$.SetLine($1.Pos.Line)
   181              $$.SetLastLine($4.LastLine())
   182          } | 
   183          TLocal namelist '=' exprlist {
   184              $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4}
   185              $$.SetLine($1.Pos.Line)
   186          } |
   187          TLocal namelist {
   188              $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}}
   189              $$.SetLine($1.Pos.Line)
   190          }
   191  
   192  elseifs: 
   193          {
   194              $$ = []ast.Stmt{}
   195          } | 
   196          elseifs TElseIf expr TThen block {
   197              $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5})
   198              $$[len($$)-1].SetLine($2.Pos.Line)
   199          }
   200  
   201  laststat:
   202          TReturn {
   203              $$ = &ast.ReturnStmt{Exprs:nil}
   204              $$.SetLine($1.Pos.Line)
   205          } |
   206          TReturn exprlist {
   207              $$ = &ast.ReturnStmt{Exprs:$2}
   208              $$.SetLine($1.Pos.Line)
   209          } |
   210          TBreak  {
   211              $$ = &ast.BreakStmt{}
   212              $$.SetLine($1.Pos.Line)
   213          }
   214  
   215  funcname: 
   216          funcname1 {
   217              $$ = $1
   218          } |
   219          funcname1 ':' TIdent {
   220              $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str}
   221          }
   222  
   223  funcname1:
   224          TIdent {
   225              $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}}
   226              $$.Func.SetLine($1.Pos.Line)
   227          } | 
   228          funcname1 '.' TIdent {
   229              key:= &ast.StringExpr{Value:$3.Str}
   230              key.SetLine($3.Pos.Line)
   231              fn := &ast.AttrGetExpr{Object: $1.Func, Key: key}
   232              fn.SetLine($3.Pos.Line)
   233              $$ = &ast.FuncName{Func: fn}
   234          }
   235  
   236  varlist:
   237          var {
   238              $$ = []ast.Expr{$1}
   239          } | 
   240          varlist ',' var {
   241              $$ = append($1, $3)
   242          }
   243  
   244  var:
   245          TIdent {
   246              $$ = &ast.IdentExpr{Value:$1.Str}
   247              $$.SetLine($1.Pos.Line)
   248          } |
   249          prefixexp '[' expr ']' {
   250              $$ = &ast.AttrGetExpr{Object: $1, Key: $3}
   251              $$.SetLine($1.Line())
   252          } | 
   253          prefixexp '.' TIdent {
   254              key := &ast.StringExpr{Value:$3.Str}
   255              key.SetLine($3.Pos.Line)
   256              $$ = &ast.AttrGetExpr{Object: $1, Key: key}
   257              $$.SetLine($1.Line())
   258          }
   259  
   260  namelist:
   261          TIdent {
   262              $$ = []string{$1.Str}
   263          } | 
   264          namelist ','  TIdent {
   265              $$ = append($1, $3.Str)
   266          }
   267  
   268  exprlist:
   269          expr {
   270              $$ = []ast.Expr{$1}
   271          } |
   272          exprlist ',' expr {
   273              $$ = append($1, $3)
   274          }
   275  
   276  expr:
   277          TNil {
   278              $$ = &ast.NilExpr{}
   279              $$.SetLine($1.Pos.Line)
   280          } | 
   281          TFalse {
   282              $$ = &ast.FalseExpr{}
   283              $$.SetLine($1.Pos.Line)
   284          } | 
   285          TTrue {
   286              $$ = &ast.TrueExpr{}
   287              $$.SetLine($1.Pos.Line)
   288          } | 
   289          TNumber {
   290              $$ = &ast.NumberExpr{Value: $1.Str}
   291              $$.SetLine($1.Pos.Line)
   292          } | 
   293          T3Comma {
   294              $$ = &ast.Comma3Expr{}
   295              $$.SetLine($1.Pos.Line)
   296          } |
   297          function {
   298              $$ = $1
   299          } | 
   300          prefixexp {
   301              $$ = $1
   302          } |
   303          string {
   304              $$ = $1
   305          } |
   306          tableconstructor {
   307              $$ = $1
   308          } |
   309          expr TOr expr {
   310              $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3}
   311              $$.SetLine($1.Line())
   312          } |
   313          expr TAnd expr {
   314              $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3}
   315              $$.SetLine($1.Line())
   316          } |
   317          expr '>' expr {
   318              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3}
   319              $$.SetLine($1.Line())
   320          } |
   321          expr '<' expr {
   322              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3}
   323              $$.SetLine($1.Line())
   324          } |
   325          expr TGte expr {
   326              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3}
   327              $$.SetLine($1.Line())
   328          } |
   329          expr TLte expr {
   330              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3}
   331              $$.SetLine($1.Line())
   332          } |
   333          expr TEqeq expr {
   334              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3}
   335              $$.SetLine($1.Line())
   336          } |
   337          expr TNeq expr {
   338              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3}
   339              $$.SetLine($1.Line())
   340          } |
   341          expr T2Comma expr {
   342              $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3}
   343              $$.SetLine($1.Line())
   344          } |
   345          expr '+' expr {
   346              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3}
   347              $$.SetLine($1.Line())
   348          } |
   349          expr '-' expr {
   350              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3}
   351              $$.SetLine($1.Line())
   352          } |
   353          expr '*' expr {
   354              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3}
   355              $$.SetLine($1.Line())
   356          } |
   357          expr '/' expr {
   358              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3}
   359              $$.SetLine($1.Line())
   360          } |
   361          expr '%' expr {
   362              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3}
   363              $$.SetLine($1.Line())
   364          } |
   365          expr '^' expr {
   366              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3}
   367              $$.SetLine($1.Line())
   368          } |
   369          '-' expr %prec UNARY {
   370              $$ = &ast.UnaryMinusOpExpr{Expr: $2}
   371              $$.SetLine($2.Line())
   372          } |
   373          TNot expr %prec UNARY {
   374              $$ = &ast.UnaryNotOpExpr{Expr: $2}
   375              $$.SetLine($2.Line())
   376          } |
   377          '#' expr %prec UNARY {
   378              $$ = &ast.UnaryLenOpExpr{Expr: $2}
   379              $$.SetLine($2.Line())
   380          }
   381  
   382  string: 
   383          TString {
   384              $$ = &ast.StringExpr{Value: $1.Str}
   385              $$.SetLine($1.Pos.Line)
   386          } 
   387  
   388  prefixexp:
   389          var {
   390              $$ = $1
   391          } |
   392          afunctioncall {
   393              $$ = $1
   394          } |
   395          functioncall {
   396              $$ = $1
   397          } |
   398          '(' expr ')' {
   399              $$ = $2
   400              $$.SetLine($1.Pos.Line)
   401          }
   402  
   403  afunctioncall:
   404          '(' functioncall ')' {
   405              $2.(*ast.FuncCallExpr).AdjustRet = true
   406              $$ = $2
   407          }
   408  
   409  functioncall:
   410          prefixexp args {
   411              $$ = &ast.FuncCallExpr{Func: $1, Args: $2}
   412              $$.SetLine($1.Line())
   413          } |
   414          prefixexp ':' TIdent args {
   415              $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4}
   416              $$.SetLine($1.Line())
   417          }
   418  
   419  args:
   420          '(' ')' {
   421              if yylex.(*Lexer).PNewLine {
   422                 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
   423              }
   424              $$ = []ast.Expr{}
   425          } |
   426          '(' exprlist ')' {
   427              if yylex.(*Lexer).PNewLine {
   428                 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
   429              }
   430              $$ = $2
   431          } |
   432          tableconstructor {
   433              $$ = []ast.Expr{$1}
   434          } | 
   435          string {
   436              $$ = []ast.Expr{$1}
   437          }
   438  
   439  function:
   440          TFunction funcbody {
   441              $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts}
   442              $$.SetLine($1.Pos.Line)
   443              $$.SetLastLine($2.LastLine())
   444          }
   445  
   446  funcbody:
   447          '(' parlist ')' block TEnd {
   448              $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4}
   449              $$.SetLine($1.Pos.Line)
   450              $$.SetLastLine($5.Pos.Line)
   451          } | 
   452          '(' ')' block TEnd {
   453              $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3}
   454              $$.SetLine($1.Pos.Line)
   455              $$.SetLastLine($4.Pos.Line)
   456          }
   457  
   458  parlist:
   459          T3Comma {
   460              $$ = &ast.ParList{HasVargs: true, Names: []string{}}
   461          } | 
   462          namelist {
   463            $$ = &ast.ParList{HasVargs: false, Names: []string{}}
   464            $$.Names = append($$.Names, $1...)
   465          } | 
   466          namelist ',' T3Comma {
   467            $$ = &ast.ParList{HasVargs: true, Names: []string{}}
   468            $$.Names = append($$.Names, $1...)
   469          }
   470  
   471  
   472  tableconstructor:
   473          '{' '}' {
   474              $$ = &ast.TableExpr{Fields: []*ast.Field{}}
   475              $$.SetLine($1.Pos.Line)
   476          } |
   477          '{' fieldlist '}' {
   478              $$ = &ast.TableExpr{Fields: $2}
   479              $$.SetLine($1.Pos.Line)
   480          }
   481  
   482  
   483  fieldlist:
   484          field {
   485              $$ = []*ast.Field{$1}
   486          } | 
   487          fieldlist fieldsep field {
   488              $$ = append($1, $3)
   489          } | 
   490          fieldlist fieldsep {
   491              $$ = $1
   492          }
   493  
   494  field:
   495          TIdent '=' expr {
   496              $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3}
   497              $$.Key.SetLine($1.Pos.Line)
   498          } | 
   499          '[' expr ']' '=' expr {
   500              $$ = &ast.Field{Key: $2, Value: $5}
   501          } |
   502          expr {
   503              $$ = &ast.Field{Value: $1}
   504          }
   505  
   506  fieldsep:
   507          ',' {
   508              $$ = ","
   509          } | 
   510          ';' {
   511              $$ = ";"
   512          }
   513  
   514  %%
   515  
   516  func TokenName(c int) string {
   517  	if c >= TAnd && c-TAnd < len(yyToknames) {
   518  		if yyToknames[c-TAnd] != "" {
   519  			return yyToknames[c-TAnd]
   520  		}
   521  	}
   522      return string([]byte{byte(c)})
   523  }
   524