Project structure refactor:

- Change package name general_server to gateway
- Changing the structure of directories and packages
- Adding vendor to the project
This commit is contained in:
2025-07-28 20:16:40 +03:00
parent 19b699d92b
commit ec94df5f4a
786 changed files with 357010 additions and 357 deletions

7
vendor/github.com/yuin/gopher-lua/parse/Makefile generated vendored Normal file
View File

@@ -0,0 +1,7 @@
all : parser.go
parser.go : parser.go.y
goyacc -o $@ parser.go.y; [ -f y.output ] && ( rm -f y.output )
clean:
rm -f parser.go

549
vendor/github.com/yuin/gopher-lua/parse/lexer.go generated vendored Normal file
View File

@@ -0,0 +1,549 @@
package parse
import (
"bufio"
"bytes"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"github.com/yuin/gopher-lua/ast"
)
const EOF = -1
const whitespace1 = 1<<'\t' | 1<<' '
const whitespace2 = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
type Error struct {
Pos ast.Position
Message string
Token string
}
func (e *Error) Error() string {
pos := e.Pos
if pos.Line == EOF {
return fmt.Sprintf("%v at EOF: %s\n", pos.Source, e.Message)
} else {
return fmt.Sprintf("%v line:%d(column:%d) near '%v': %s\n", pos.Source, pos.Line, pos.Column, e.Token, e.Message)
}
}
func writeChar(buf *bytes.Buffer, c int) { buf.WriteByte(byte(c)) }
func isDecimal(ch int) bool { return '0' <= ch && ch <= '9' }
func isIdent(ch int, pos int) bool {
return ch == '_' || 'A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' || isDecimal(ch) && pos > 0
}
func isDigit(ch int) bool {
return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F'
}
type Scanner struct {
Pos ast.Position
reader *bufio.Reader
}
func NewScanner(reader io.Reader, source string) *Scanner {
return &Scanner{
Pos: ast.Position{
Source: source,
Line: 1,
Column: 0,
},
reader: bufio.NewReaderSize(reader, 4096),
}
}
func (sc *Scanner) Error(tok string, msg string) *Error { return &Error{sc.Pos, msg, tok} }
func (sc *Scanner) TokenError(tok ast.Token, msg string) *Error { return &Error{tok.Pos, msg, tok.Str} }
func (sc *Scanner) readNext() int {
ch, err := sc.reader.ReadByte()
if err == io.EOF {
return EOF
}
return int(ch)
}
func (sc *Scanner) Newline(ch int) {
if ch < 0 {
return
}
sc.Pos.Line += 1
sc.Pos.Column = 0
next := sc.Peek()
if ch == '\n' && next == '\r' || ch == '\r' && next == '\n' {
sc.reader.ReadByte()
}
}
func (sc *Scanner) Next() int {
ch := sc.readNext()
switch ch {
case '\n', '\r':
sc.Newline(ch)
ch = int('\n')
case EOF:
sc.Pos.Line = EOF
sc.Pos.Column = 0
default:
sc.Pos.Column++
}
return ch
}
func (sc *Scanner) Peek() int {
ch := sc.readNext()
if ch != EOF {
sc.reader.UnreadByte()
}
return ch
}
func (sc *Scanner) skipWhiteSpace(whitespace int64) int {
ch := sc.Next()
for ; whitespace&(1<<uint(ch)) != 0; ch = sc.Next() {
}
return ch
}
func (sc *Scanner) skipComments(ch int) error {
// multiline comment
if sc.Peek() == '[' {
ch = sc.Next()
if sc.Peek() == '[' || sc.Peek() == '=' {
var buf bytes.Buffer
if err := sc.scanMultilineString(sc.Next(), &buf); err != nil {
return sc.Error(buf.String(), "invalid multiline comment")
}
return nil
}
}
for {
if ch == '\n' || ch == '\r' || ch < 0 {
break
}
ch = sc.Next()
}
return nil
}
func (sc *Scanner) scanIdent(ch int, buf *bytes.Buffer) error {
writeChar(buf, ch)
for isIdent(sc.Peek(), 1) {
writeChar(buf, sc.Next())
}
return nil
}
func (sc *Scanner) scanDecimal(ch int, buf *bytes.Buffer) error {
writeChar(buf, ch)
for isDecimal(sc.Peek()) {
writeChar(buf, sc.Next())
}
return nil
}
func (sc *Scanner) scanNumber(ch int, buf *bytes.Buffer) error {
if ch == '0' { // octal
if sc.Peek() == 'x' || sc.Peek() == 'X' {
writeChar(buf, ch)
writeChar(buf, sc.Next())
hasvalue := false
for isDigit(sc.Peek()) {
writeChar(buf, sc.Next())
hasvalue = true
}
if !hasvalue {
return sc.Error(buf.String(), "illegal hexadecimal number")
}
return nil
} else if sc.Peek() != '.' && isDecimal(sc.Peek()) {
ch = sc.Next()
}
}
sc.scanDecimal(ch, buf)
if sc.Peek() == '.' {
sc.scanDecimal(sc.Next(), buf)
}
if ch = sc.Peek(); ch == 'e' || ch == 'E' {
writeChar(buf, sc.Next())
if ch = sc.Peek(); ch == '-' || ch == '+' {
writeChar(buf, sc.Next())
}
sc.scanDecimal(sc.Next(), buf)
}
return nil
}
func (sc *Scanner) scanString(quote int, buf *bytes.Buffer) error {
ch := sc.Next()
for ch != quote {
if ch == '\n' || ch == '\r' || ch < 0 {
return sc.Error(buf.String(), "unterminated string")
}
if ch == '\\' {
if err := sc.scanEscape(ch, buf); err != nil {
return err
}
} else {
writeChar(buf, ch)
}
ch = sc.Next()
}
return nil
}
func (sc *Scanner) scanEscape(ch int, buf *bytes.Buffer) error {
ch = sc.Next()
switch ch {
case 'a':
buf.WriteByte('\a')
case 'b':
buf.WriteByte('\b')
case 'f':
buf.WriteByte('\f')
case 'n':
buf.WriteByte('\n')
case 'r':
buf.WriteByte('\r')
case 't':
buf.WriteByte('\t')
case 'v':
buf.WriteByte('\v')
case '\\':
buf.WriteByte('\\')
case '"':
buf.WriteByte('"')
case '\'':
buf.WriteByte('\'')
case '\n':
buf.WriteByte('\n')
case '\r':
buf.WriteByte('\n')
sc.Newline('\r')
default:
if '0' <= ch && ch <= '9' {
bytes := []byte{byte(ch)}
for i := 0; i < 2 && isDecimal(sc.Peek()); i++ {
bytes = append(bytes, byte(sc.Next()))
}
val, _ := strconv.ParseInt(string(bytes), 10, 32)
writeChar(buf, int(val))
} else {
writeChar(buf, ch)
}
}
return nil
}
func (sc *Scanner) countSep(ch int) (int, int) {
count := 0
for ; ch == '='; count = count + 1 {
ch = sc.Next()
}
return count, ch
}
func (sc *Scanner) scanMultilineString(ch int, buf *bytes.Buffer) error {
var count1, count2 int
count1, ch = sc.countSep(ch)
if ch != '[' {
return sc.Error(string(rune(ch)), "invalid multiline string")
}
ch = sc.Next()
if ch == '\n' || ch == '\r' {
ch = sc.Next()
}
for {
if ch < 0 {
return sc.Error(buf.String(), "unterminated multiline string")
} else if ch == ']' {
count2, ch = sc.countSep(sc.Next())
if count1 == count2 && ch == ']' {
goto finally
}
buf.WriteByte(']')
buf.WriteString(strings.Repeat("=", count2))
continue
}
writeChar(buf, ch)
ch = sc.Next()
}
finally:
return nil
}
var reservedWords = map[string]int{
"and": TAnd, "break": TBreak, "do": TDo, "else": TElse, "elseif": TElseIf,
"end": TEnd, "false": TFalse, "for": TFor, "function": TFunction,
"if": TIf, "in": TIn, "local": TLocal, "nil": TNil, "not": TNot, "or": TOr,
"return": TReturn, "repeat": TRepeat, "then": TThen, "true": TTrue,
"until": TUntil, "while": TWhile, "goto": TGoto}
func (sc *Scanner) Scan(lexer *Lexer) (ast.Token, error) {
redo:
var err error
tok := ast.Token{}
newline := false
ch := sc.skipWhiteSpace(whitespace1)
if ch == '\n' || ch == '\r' {
newline = true
ch = sc.skipWhiteSpace(whitespace2)
}
if ch == '(' && lexer.PrevTokenType == ')' {
lexer.PNewLine = newline
} else {
lexer.PNewLine = false
}
var _buf bytes.Buffer
buf := &_buf
tok.Pos = sc.Pos
switch {
case isIdent(ch, 0):
tok.Type = TIdent
err = sc.scanIdent(ch, buf)
tok.Str = buf.String()
if err != nil {
goto finally
}
if typ, ok := reservedWords[tok.Str]; ok {
tok.Type = typ
}
case isDecimal(ch):
tok.Type = TNumber
err = sc.scanNumber(ch, buf)
tok.Str = buf.String()
default:
switch ch {
case EOF:
tok.Type = EOF
case '-':
if sc.Peek() == '-' {
err = sc.skipComments(sc.Next())
if err != nil {
goto finally
}
goto redo
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '"', '\'':
tok.Type = TString
err = sc.scanString(ch, buf)
tok.Str = buf.String()
case '[':
if c := sc.Peek(); c == '[' || c == '=' {
tok.Type = TString
err = sc.scanMultilineString(sc.Next(), buf)
tok.Str = buf.String()
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '=':
if sc.Peek() == '=' {
tok.Type = TEqeq
tok.Str = "=="
sc.Next()
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '~':
if sc.Peek() == '=' {
tok.Type = TNeq
tok.Str = "~="
sc.Next()
} else {
err = sc.Error("~", "Invalid '~' token")
}
case '<':
if sc.Peek() == '=' {
tok.Type = TLte
tok.Str = "<="
sc.Next()
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '>':
if sc.Peek() == '=' {
tok.Type = TGte
tok.Str = ">="
sc.Next()
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '.':
ch2 := sc.Peek()
switch {
case isDecimal(ch2):
tok.Type = TNumber
err = sc.scanNumber(ch, buf)
tok.Str = buf.String()
case ch2 == '.':
writeChar(buf, ch)
writeChar(buf, sc.Next())
if sc.Peek() == '.' {
writeChar(buf, sc.Next())
tok.Type = T3Comma
} else {
tok.Type = T2Comma
}
default:
tok.Type = '.'
}
tok.Str = buf.String()
case ':':
if sc.Peek() == ':' {
tok.Type = T2Colon
tok.Str = "::"
sc.Next()
} else {
tok.Type = ch
tok.Str = string(rune(ch))
}
case '+', '*', '/', '%', '^', '#', '(', ')', '{', '}', ']', ';', ',':
tok.Type = ch
tok.Str = string(rune(ch))
default:
writeChar(buf, ch)
err = sc.Error(buf.String(), "Invalid token")
goto finally
}
}
finally:
tok.Name = TokenName(int(tok.Type))
return tok, err
}
// yacc interface {{{
type Lexer struct {
scanner *Scanner
Stmts []ast.Stmt
PNewLine bool
Token ast.Token
PrevTokenType int
}
func (lx *Lexer) Lex(lval *yySymType) int {
lx.PrevTokenType = lx.Token.Type
tok, err := lx.scanner.Scan(lx)
if err != nil {
panic(err)
}
if tok.Type < 0 {
return 0
}
lval.token = tok
lx.Token = tok
return int(tok.Type)
}
func (lx *Lexer) Error(message string) {
panic(lx.scanner.Error(lx.Token.Str, message))
}
func (lx *Lexer) TokenError(tok ast.Token, message string) {
panic(lx.scanner.TokenError(tok, message))
}
func Parse(reader io.Reader, name string) (chunk []ast.Stmt, err error) {
lexer := &Lexer{NewScanner(reader, name), nil, false, ast.Token{Str: ""}, TNil}
chunk = nil
defer func() {
if e := recover(); e != nil {
err, _ = e.(error)
}
}()
yyParse(lexer)
chunk = lexer.Stmts
return
}
// }}}
// Dump {{{
func isInlineDumpNode(rv reflect.Value) bool {
switch rv.Kind() {
case reflect.Struct, reflect.Slice, reflect.Interface, reflect.Ptr:
return false
default:
return true
}
}
func dump(node interface{}, level int, s string) string {
rt := reflect.TypeOf(node)
if fmt.Sprint(rt) == "<nil>" {
return strings.Repeat(s, level) + "<nil>"
}
rv := reflect.ValueOf(node)
buf := []string{}
switch rt.Kind() {
case reflect.Slice:
if rv.Len() == 0 {
return strings.Repeat(s, level) + "<empty>"
}
for i := 0; i < rv.Len(); i++ {
buf = append(buf, dump(rv.Index(i).Interface(), level, s))
}
case reflect.Ptr:
vt := rv.Elem()
tt := rt.Elem()
indicies := []int{}
for i := 0; i < tt.NumField(); i++ {
if strings.Index(tt.Field(i).Name, "Base") > -1 {
continue
}
indicies = append(indicies, i)
}
switch {
case len(indicies) == 0:
return strings.Repeat(s, level) + "<empty>"
case len(indicies) == 1 && isInlineDumpNode(vt.Field(indicies[0])):
for _, i := range indicies {
buf = append(buf, strings.Repeat(s, level)+"- Node$"+tt.Name()+": "+dump(vt.Field(i).Interface(), 0, s))
}
default:
buf = append(buf, strings.Repeat(s, level)+"- Node$"+tt.Name())
for _, i := range indicies {
if isInlineDumpNode(vt.Field(i)) {
inf := dump(vt.Field(i).Interface(), 0, s)
buf = append(buf, strings.Repeat(s, level+1)+tt.Field(i).Name+": "+inf)
} else {
buf = append(buf, strings.Repeat(s, level+1)+tt.Field(i).Name+": ")
buf = append(buf, dump(vt.Field(i).Interface(), level+2, s))
}
}
}
default:
buf = append(buf, strings.Repeat(s, level)+fmt.Sprint(node))
}
return strings.Join(buf, "\n")
}
func Dump(chunk []ast.Stmt) string {
return dump(chunk, 0, " ")
}
// }}

1383
vendor/github.com/yuin/gopher-lua/parse/parser.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

535
vendor/github.com/yuin/gopher-lua/parse/parser.go.y generated vendored Normal file
View File

@@ -0,0 +1,535 @@
%{
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 TGoto
/* Literals */
%token<token> TEqeq TNeq TLte TGte T2Comma T3Comma T2Colon 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)
} |
T2Colon TIdent T2Colon {
$$ = &ast.LabelStmt{Name: $2.Str}
$$.SetLine($1.Pos.Line)
} |
TGoto TIdent {
$$ = &ast.GotoStmt{Label: $2.Str}
$$.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 ')' {
if ex, ok := $2.(*ast.Comma3Expr); ok {
ex.AdjustRet = true
}
$$ = $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)})
}