github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/parse/parser.go.y (about)

     1  %{
     2  package parse
     3  
     4  import (
     5    "github.com/yuin/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 TGoto
    56  
    57  /* Literals */
    58  %token<token> TEqeq TNeq TLte TGte T2Comma T3Comma T2Colon 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          T2Colon TIdent T2Colon {
   192              $$ = &ast.LabelStmt{Name: $2.Str}
   193              $$.SetLine($1.Pos.Line)
   194          } |
   195          TGoto TIdent {
   196              $$ = &ast.GotoStmt{Label: $2.Str}
   197              $$.SetLine($1.Pos.Line)
   198          }
   199  
   200  elseifs: 
   201          {
   202              $$ = []ast.Stmt{}
   203          } | 
   204          elseifs TElseIf expr TThen block {
   205              $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5})
   206              $$[len($$)-1].SetLine($2.Pos.Line)
   207          }
   208  
   209  laststat:
   210          TReturn {
   211              $$ = &ast.ReturnStmt{Exprs:nil}
   212              $$.SetLine($1.Pos.Line)
   213          } |
   214          TReturn exprlist {
   215              $$ = &ast.ReturnStmt{Exprs:$2}
   216              $$.SetLine($1.Pos.Line)
   217          } |
   218          TBreak  {
   219              $$ = &ast.BreakStmt{}
   220              $$.SetLine($1.Pos.Line)
   221          }
   222  
   223  funcname: 
   224          funcname1 {
   225              $$ = $1
   226          } |
   227          funcname1 ':' TIdent {
   228              $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str}
   229          }
   230  
   231  funcname1:
   232          TIdent {
   233              $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}}
   234              $$.Func.SetLine($1.Pos.Line)
   235          } | 
   236          funcname1 '.' TIdent {
   237              key:= &ast.StringExpr{Value:$3.Str}
   238              key.SetLine($3.Pos.Line)
   239              fn := &ast.AttrGetExpr{Object: $1.Func, Key: key}
   240              fn.SetLine($3.Pos.Line)
   241              $$ = &ast.FuncName{Func: fn}
   242          }
   243  
   244  varlist:
   245          var {
   246              $$ = []ast.Expr{$1}
   247          } | 
   248          varlist ',' var {
   249              $$ = append($1, $3)
   250          }
   251  
   252  var:
   253          TIdent {
   254              $$ = &ast.IdentExpr{Value:$1.Str}
   255              $$.SetLine($1.Pos.Line)
   256          } |
   257          prefixexp '[' expr ']' {
   258              $$ = &ast.AttrGetExpr{Object: $1, Key: $3}
   259              $$.SetLine($1.Line())
   260          } | 
   261          prefixexp '.' TIdent {
   262              key := &ast.StringExpr{Value:$3.Str}
   263              key.SetLine($3.Pos.Line)
   264              $$ = &ast.AttrGetExpr{Object: $1, Key: key}
   265              $$.SetLine($1.Line())
   266          }
   267  
   268  namelist:
   269          TIdent {
   270              $$ = []string{$1.Str}
   271          } | 
   272          namelist ','  TIdent {
   273              $$ = append($1, $3.Str)
   274          }
   275  
   276  exprlist:
   277          expr {
   278              $$ = []ast.Expr{$1}
   279          } |
   280          exprlist ',' expr {
   281              $$ = append($1, $3)
   282          }
   283  
   284  expr:
   285          TNil {
   286              $$ = &ast.NilExpr{}
   287              $$.SetLine($1.Pos.Line)
   288          } | 
   289          TFalse {
   290              $$ = &ast.FalseExpr{}
   291              $$.SetLine($1.Pos.Line)
   292          } | 
   293          TTrue {
   294              $$ = &ast.TrueExpr{}
   295              $$.SetLine($1.Pos.Line)
   296          } | 
   297          TNumber {
   298              $$ = &ast.NumberExpr{Value: $1.Str}
   299              $$.SetLine($1.Pos.Line)
   300          } | 
   301          T3Comma {
   302              $$ = &ast.Comma3Expr{}
   303              $$.SetLine($1.Pos.Line)
   304          } |
   305          function {
   306              $$ = $1
   307          } | 
   308          prefixexp {
   309              $$ = $1
   310          } |
   311          string {
   312              $$ = $1
   313          } |
   314          tableconstructor {
   315              $$ = $1
   316          } |
   317          expr TOr expr {
   318              $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3}
   319              $$.SetLine($1.Line())
   320          } |
   321          expr TAnd expr {
   322              $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3}
   323              $$.SetLine($1.Line())
   324          } |
   325          expr '>' expr {
   326              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3}
   327              $$.SetLine($1.Line())
   328          } |
   329          expr '<' expr {
   330              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3}
   331              $$.SetLine($1.Line())
   332          } |
   333          expr TGte expr {
   334              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3}
   335              $$.SetLine($1.Line())
   336          } |
   337          expr TLte expr {
   338              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3}
   339              $$.SetLine($1.Line())
   340          } |
   341          expr TEqeq expr {
   342              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3}
   343              $$.SetLine($1.Line())
   344          } |
   345          expr TNeq expr {
   346              $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3}
   347              $$.SetLine($1.Line())
   348          } |
   349          expr T2Comma expr {
   350              $$ = &ast.StringConcatOpExpr{Lhs: $1, 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 '%' expr {
   370              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3}
   371              $$.SetLine($1.Line())
   372          } |
   373          expr '^' expr {
   374              $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3}
   375              $$.SetLine($1.Line())
   376          } |
   377          '-' expr %prec UNARY {
   378              $$ = &ast.UnaryMinusOpExpr{Expr: $2}
   379              $$.SetLine($2.Line())
   380          } |
   381          TNot expr %prec UNARY {
   382              $$ = &ast.UnaryNotOpExpr{Expr: $2}
   383              $$.SetLine($2.Line())
   384          } |
   385          '#' expr %prec UNARY {
   386              $$ = &ast.UnaryLenOpExpr{Expr: $2}
   387              $$.SetLine($2.Line())
   388          }
   389  
   390  string: 
   391          TString {
   392              $$ = &ast.StringExpr{Value: $1.Str}
   393              $$.SetLine($1.Pos.Line)
   394          } 
   395  
   396  prefixexp:
   397          var {
   398              $$ = $1
   399          } |
   400          afunctioncall {
   401              $$ = $1
   402          } |
   403          functioncall {
   404              $$ = $1
   405          } |
   406          '(' expr ')' {
   407              if ex, ok := $2.(*ast.Comma3Expr); ok {
   408                  ex.AdjustRet = true
   409              }
   410              $$ = $2
   411              $$.SetLine($1.Pos.Line)
   412          }
   413  
   414  afunctioncall:
   415          '(' functioncall ')' {
   416              $2.(*ast.FuncCallExpr).AdjustRet = true
   417              $$ = $2
   418          }
   419  
   420  functioncall:
   421          prefixexp args {
   422              $$ = &ast.FuncCallExpr{Func: $1, Args: $2}
   423              $$.SetLine($1.Line())
   424          } |
   425          prefixexp ':' TIdent args {
   426              $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4}
   427              $$.SetLine($1.Line())
   428          }
   429  
   430  args:
   431          '(' ')' {
   432              if yylex.(*Lexer).PNewLine {
   433                 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
   434              }
   435              $$ = []ast.Expr{}
   436          } |
   437          '(' exprlist ')' {
   438              if yylex.(*Lexer).PNewLine {
   439                 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
   440              }
   441              $$ = $2
   442          } |
   443          tableconstructor {
   444              $$ = []ast.Expr{$1}
   445          } | 
   446          string {
   447              $$ = []ast.Expr{$1}
   448          }
   449  
   450  function:
   451          TFunction funcbody {
   452              $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts}
   453              $$.SetLine($1.Pos.Line)
   454              $$.SetLastLine($2.LastLine())
   455          }
   456  
   457  funcbody:
   458          '(' parlist ')' block TEnd {
   459              $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4}
   460              $$.SetLine($1.Pos.Line)
   461              $$.SetLastLine($5.Pos.Line)
   462          } | 
   463          '(' ')' block TEnd {
   464              $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3}
   465              $$.SetLine($1.Pos.Line)
   466              $$.SetLastLine($4.Pos.Line)
   467          }
   468  
   469  parlist:
   470          T3Comma {
   471              $$ = &ast.ParList{HasVargs: true, Names: []string{}}
   472          } | 
   473          namelist {
   474            $$ = &ast.ParList{HasVargs: false, Names: []string{}}
   475            $$.Names = append($$.Names, $1...)
   476          } | 
   477          namelist ',' T3Comma {
   478            $$ = &ast.ParList{HasVargs: true, Names: []string{}}
   479            $$.Names = append($$.Names, $1...)
   480          }
   481  
   482  
   483  tableconstructor:
   484          '{' '}' {
   485              $$ = &ast.TableExpr{Fields: []*ast.Field{}}
   486              $$.SetLine($1.Pos.Line)
   487          } |
   488          '{' fieldlist '}' {
   489              $$ = &ast.TableExpr{Fields: $2}
   490              $$.SetLine($1.Pos.Line)
   491          }
   492  
   493  
   494  fieldlist:
   495          field {
   496              $$ = []*ast.Field{$1}
   497          } | 
   498          fieldlist fieldsep field {
   499              $$ = append($1, $3)
   500          } | 
   501          fieldlist fieldsep {
   502              $$ = $1
   503          }
   504  
   505  field:
   506          TIdent '=' expr {
   507              $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3}
   508              $$.Key.SetLine($1.Pos.Line)
   509          } | 
   510          '[' expr ']' '=' expr {
   511              $$ = &ast.Field{Key: $2, Value: $5}
   512          } |
   513          expr {
   514              $$ = &ast.Field{Value: $1}
   515          }
   516  
   517  fieldsep:
   518          ',' {
   519              $$ = ","
   520          } | 
   521          ';' {
   522              $$ = ";"
   523          }
   524  
   525  %%
   526  
   527  func TokenName(c int) string {
   528  	if c >= TAnd && c-TAnd < len(yyToknames) {
   529  		if yyToknames[c-TAnd] != "" {
   530  			return yyToknames[c-TAnd]
   531  		}
   532  	}
   533      return string([]byte{byte(c)})
   534  }
   535