route/vendor/github.com/yuin/gopher-lua/parse/parser.go.y

525 lines
14 KiB
Plaintext

%{
package parse
import (
"github.com/yuin/gopher-lua/ast"
)
%}
%type<stmts> chunk
%type<stmts> chunk1
%type<stmts> block
%type<stmt> stat
%type<stmts> elseifs
%type<stmt> laststat
%type<funcname> funcname
%type<funcname> funcname1
%type<exprlist> varlist
%type<expr> var
%type<namelist> namelist
%type<exprlist> exprlist
%type<expr> expr
%type<expr> string
%type<expr> prefixexp
%type<expr> functioncall
%type<expr> afunctioncall
%type<exprlist> args
%type<expr> function
%type<funcexpr> funcbody
%type<parlist> parlist
%type<expr> tableconstructor
%type<fieldlist> fieldlist
%type<field> field
%type<fieldsep> fieldsep
%union {
token ast.Token
stmts []ast.Stmt
stmt ast.Stmt
funcname *ast.FuncName
funcexpr *ast.FunctionExpr
exprlist []ast.Expr
expr ast.Expr
fieldlist []*ast.Field
field *ast.Field
fieldsep string
namelist []string
parlist *ast.ParList
}
/* Reserved words */
%token<token> TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile
/* Literals */
%token<token> TEqeq TNeq TLte TGte T2Comma T3Comma TIdent TNumber TString '{' '('
/* Operators */
%left TOr
%left TAnd
%left '>' '<' TGte TLte TEqeq TNeq
%right T2Comma
%left '+' '-'
%left '*' '/' '%'
%right UNARY /* not # -(unary) */
%right '^'
%%
chunk:
chunk1 {
$$ = $1
if l, ok := yylex.(*Lexer); ok {
l.Stmts = $$
}
} |
chunk1 laststat {
$$ = append($1, $2)
if l, ok := yylex.(*Lexer); ok {
l.Stmts = $$
}
} |
chunk1 laststat ';' {
$$ = append($1, $2)
if l, ok := yylex.(*Lexer); ok {
l.Stmts = $$
}
}
chunk1:
{
$$ = []ast.Stmt{}
} |
chunk1 stat {
$$ = append($1, $2)
} |
chunk1 ';' {
$$ = $1
}
block:
chunk {
$$ = $1
}
stat:
varlist '=' exprlist {
$$ = &ast.AssignStmt{Lhs: $1, Rhs: $3}
$$.SetLine($1[0].Line())
} |
/* 'stat = functioncal' causes a reduce/reduce conflict */
prefixexp {
if _, ok := $1.(*ast.FuncCallExpr); !ok {
yylex.(*Lexer).Error("parse error")
} else {
$$ = &ast.FuncCallStmt{Expr: $1}
$$.SetLine($1.Line())
}
} |
TDo block TEnd {
$$ = &ast.DoBlockStmt{Stmts: $2}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($3.Pos.Line)
} |
TWhile expr TDo block TEnd {
$$ = &ast.WhileStmt{Condition: $2, Stmts: $4}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($5.Pos.Line)
} |
TRepeat block TUntil expr {
$$ = &ast.RepeatStmt{Condition: $4, Stmts: $2}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($4.Line())
} |
TIf expr TThen block elseifs TEnd {
$$ = &ast.IfStmt{Condition: $2, Then: $4}
cur := $$
for _, elseif := range $5 {
cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
cur = elseif
}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($6.Pos.Line)
} |
TIf expr TThen block elseifs TElse block TEnd {
$$ = &ast.IfStmt{Condition: $2, Then: $4}
cur := $$
for _, elseif := range $5 {
cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
cur = elseif
}
cur.(*ast.IfStmt).Else = $7
$$.SetLine($1.Pos.Line)
$$.SetLastLine($8.Pos.Line)
} |
TFor TIdent '=' expr ',' expr TDo block TEnd {
$$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($9.Pos.Line)
} |
TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd {
$$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($11.Pos.Line)
} |
TFor namelist TIn exprlist TDo block TEnd {
$$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($7.Pos.Line)
} |
TFunction funcname funcbody {
$$ = &ast.FuncDefStmt{Name: $2, Func: $3}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($3.LastLine())
} |
TLocal TFunction TIdent funcbody {
$$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($4.LastLine())
} |
TLocal namelist '=' exprlist {
$$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4}
$$.SetLine($1.Pos.Line)
} |
TLocal namelist {
$$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}}
$$.SetLine($1.Pos.Line)
}
elseifs:
{
$$ = []ast.Stmt{}
} |
elseifs TElseIf expr TThen block {
$$ = append($1, &ast.IfStmt{Condition: $3, Then: $5})
$$[len($$)-1].SetLine($2.Pos.Line)
}
laststat:
TReturn {
$$ = &ast.ReturnStmt{Exprs:nil}
$$.SetLine($1.Pos.Line)
} |
TReturn exprlist {
$$ = &ast.ReturnStmt{Exprs:$2}
$$.SetLine($1.Pos.Line)
} |
TBreak {
$$ = &ast.BreakStmt{}
$$.SetLine($1.Pos.Line)
}
funcname:
funcname1 {
$$ = $1
} |
funcname1 ':' TIdent {
$$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str}
}
funcname1:
TIdent {
$$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}}
$$.Func.SetLine($1.Pos.Line)
} |
funcname1 '.' TIdent {
key:= &ast.StringExpr{Value:$3.Str}
key.SetLine($3.Pos.Line)
fn := &ast.AttrGetExpr{Object: $1.Func, Key: key}
fn.SetLine($3.Pos.Line)
$$ = &ast.FuncName{Func: fn}
}
varlist:
var {
$$ = []ast.Expr{$1}
} |
varlist ',' var {
$$ = append($1, $3)
}
var:
TIdent {
$$ = &ast.IdentExpr{Value:$1.Str}
$$.SetLine($1.Pos.Line)
} |
prefixexp '[' expr ']' {
$$ = &ast.AttrGetExpr{Object: $1, Key: $3}
$$.SetLine($1.Line())
} |
prefixexp '.' TIdent {
key := &ast.StringExpr{Value:$3.Str}
key.SetLine($3.Pos.Line)
$$ = &ast.AttrGetExpr{Object: $1, Key: key}
$$.SetLine($1.Line())
}
namelist:
TIdent {
$$ = []string{$1.Str}
} |
namelist ',' TIdent {
$$ = append($1, $3.Str)
}
exprlist:
expr {
$$ = []ast.Expr{$1}
} |
exprlist ',' expr {
$$ = append($1, $3)
}
expr:
TNil {
$$ = &ast.NilExpr{}
$$.SetLine($1.Pos.Line)
} |
TFalse {
$$ = &ast.FalseExpr{}
$$.SetLine($1.Pos.Line)
} |
TTrue {
$$ = &ast.TrueExpr{}
$$.SetLine($1.Pos.Line)
} |
TNumber {
$$ = &ast.NumberExpr{Value: $1.Str}
$$.SetLine($1.Pos.Line)
} |
T3Comma {
$$ = &ast.Comma3Expr{}
$$.SetLine($1.Pos.Line)
} |
function {
$$ = $1
} |
prefixexp {
$$ = $1
} |
string {
$$ = $1
} |
tableconstructor {
$$ = $1
} |
expr TOr expr {
$$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3}
$$.SetLine($1.Line())
} |
expr TAnd expr {
$$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '>' expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '<' expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3}
$$.SetLine($1.Line())
} |
expr TGte expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3}
$$.SetLine($1.Line())
} |
expr TLte expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3}
$$.SetLine($1.Line())
} |
expr TEqeq expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3}
$$.SetLine($1.Line())
} |
expr TNeq expr {
$$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3}
$$.SetLine($1.Line())
} |
expr T2Comma expr {
$$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3}
$$.SetLine($1.Line())
} |
expr '+' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '-' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '*' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '/' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '%' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3}
$$.SetLine($1.Line())
} |
expr '^' expr {
$$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3}
$$.SetLine($1.Line())
} |
'-' expr %prec UNARY {
$$ = &ast.UnaryMinusOpExpr{Expr: $2}
$$.SetLine($2.Line())
} |
TNot expr %prec UNARY {
$$ = &ast.UnaryNotOpExpr{Expr: $2}
$$.SetLine($2.Line())
} |
'#' expr %prec UNARY {
$$ = &ast.UnaryLenOpExpr{Expr: $2}
$$.SetLine($2.Line())
}
string:
TString {
$$ = &ast.StringExpr{Value: $1.Str}
$$.SetLine($1.Pos.Line)
}
prefixexp:
var {
$$ = $1
} |
afunctioncall {
$$ = $1
} |
functioncall {
$$ = $1
} |
'(' expr ')' {
$$ = $2
$$.SetLine($1.Pos.Line)
}
afunctioncall:
'(' functioncall ')' {
$2.(*ast.FuncCallExpr).AdjustRet = true
$$ = $2
}
functioncall:
prefixexp args {
$$ = &ast.FuncCallExpr{Func: $1, Args: $2}
$$.SetLine($1.Line())
} |
prefixexp ':' TIdent args {
$$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4}
$$.SetLine($1.Line())
}
args:
'(' ')' {
if yylex.(*Lexer).PNewLine {
yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
}
$$ = []ast.Expr{}
} |
'(' exprlist ')' {
if yylex.(*Lexer).PNewLine {
yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
}
$$ = $2
} |
tableconstructor {
$$ = []ast.Expr{$1}
} |
string {
$$ = []ast.Expr{$1}
}
function:
TFunction funcbody {
$$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($2.LastLine())
}
funcbody:
'(' parlist ')' block TEnd {
$$ = &ast.FunctionExpr{ParList: $2, Stmts: $4}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($5.Pos.Line)
} |
'(' ')' block TEnd {
$$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3}
$$.SetLine($1.Pos.Line)
$$.SetLastLine($4.Pos.Line)
}
parlist:
T3Comma {
$$ = &ast.ParList{HasVargs: true, Names: []string{}}
} |
namelist {
$$ = &ast.ParList{HasVargs: false, Names: []string{}}
$$.Names = append($$.Names, $1...)
} |
namelist ',' T3Comma {
$$ = &ast.ParList{HasVargs: true, Names: []string{}}
$$.Names = append($$.Names, $1...)
}
tableconstructor:
'{' '}' {
$$ = &ast.TableExpr{Fields: []*ast.Field{}}
$$.SetLine($1.Pos.Line)
} |
'{' fieldlist '}' {
$$ = &ast.TableExpr{Fields: $2}
$$.SetLine($1.Pos.Line)
}
fieldlist:
field {
$$ = []*ast.Field{$1}
} |
fieldlist fieldsep field {
$$ = append($1, $3)
} |
fieldlist fieldsep {
$$ = $1
}
field:
TIdent '=' expr {
$$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3}
$$.Key.SetLine($1.Pos.Line)
} |
'[' expr ']' '=' expr {
$$ = &ast.Field{Key: $2, Value: $5}
} |
expr {
$$ = &ast.Field{Value: $1}
}
fieldsep:
',' {
$$ = ","
} |
';' {
$$ = ";"
}
%%
func TokenName(c int) string {
if c >= TAnd && c-TAnd < len(yyToknames) {
if yyToknames[c-TAnd] != "" {
return yyToknames[c-TAnd]
}
}
return string([]byte{byte(c)})
}