mirror of
https://github.com/kataras/iris.git
synced 2025-01-26 03:56:34 +01:00
126c4de29b
1. Fix index, including both start and end. So Literal[start:end+1] will be a valid part. 2. Replace any with string, add file param type 3. Start of making the evaluator, starting with regexp for param types (these expression can be changed or/and overriden by user later on) Former-commit-id: ab95265f953dadbf84170b543e1ff8840f9c4a14
130 lines
3.3 KiB
Go
130 lines
3.3 KiB
Go
package parser
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"gopkg.in/kataras/iris.v6/_future/ipel/ast"
|
|
"gopkg.in/kataras/iris.v6/_future/ipel/lexer"
|
|
"gopkg.in/kataras/iris.v6/_future/ipel/token"
|
|
)
|
|
|
|
type Parser struct {
|
|
l *lexer.Lexer
|
|
errors []string
|
|
}
|
|
|
|
func New(src string) *Parser {
|
|
p := new(Parser)
|
|
p.Reset(src)
|
|
return p
|
|
}
|
|
|
|
func (p *Parser) Reset(src string) {
|
|
p.l = lexer.New(src)
|
|
p.errors = []string{}
|
|
}
|
|
|
|
func (p *Parser) appendErr(format string, a ...interface{}) {
|
|
p.errors = append(p.errors, fmt.Sprintf(format, a...))
|
|
}
|
|
|
|
const DefaultParamErrorCode = 404
|
|
const DefaultParamType = ast.ParamTypeString
|
|
|
|
func parseParamFuncArg(t token.Token) (a ast.ParamFuncArg, err error) {
|
|
if t.Type == token.INT {
|
|
return ast.ParamFuncArgToInt(t.Literal)
|
|
}
|
|
return t.Literal, nil
|
|
}
|
|
|
|
func (p Parser) Error() error {
|
|
if len(p.errors) > 0 {
|
|
return fmt.Errorf(strings.Join(p.errors, "\n"))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Parser) Parse() (*ast.ParamStatement, error) {
|
|
p.errors = []string{}
|
|
|
|
stmt := &ast.ParamStatement{
|
|
ErrorCode: DefaultParamErrorCode,
|
|
Type: DefaultParamType,
|
|
}
|
|
|
|
lastParamFunc := ast.ParamFunc{}
|
|
|
|
for {
|
|
t := p.l.NextToken()
|
|
if t.Type == token.EOF {
|
|
if stmt.Name == "" {
|
|
p.appendErr("[1:] parameter name is missing")
|
|
}
|
|
break
|
|
}
|
|
|
|
switch t.Type {
|
|
case token.LBRACE:
|
|
// name, alphabetical and _, param names are not allowed to contain any number.
|
|
nextTok := p.l.NextToken()
|
|
stmt.Name = nextTok.Literal
|
|
case token.COLON:
|
|
// type
|
|
nextTok := p.l.NextToken()
|
|
paramType := ast.LookupParamType(nextTok.Literal)
|
|
if paramType == ast.ParamTypeUnExpected {
|
|
p.appendErr("[%d:%d] unexpected parameter type: %s", t.Start, t.End, nextTok.Literal)
|
|
}
|
|
stmt.Type = paramType
|
|
// param func
|
|
case token.IDENT:
|
|
lastParamFunc.Name = t.Literal
|
|
case token.LPAREN:
|
|
argValTok := p.l.NextToken()
|
|
argVal, err := parseParamFuncArg(argValTok)
|
|
if err != nil {
|
|
p.appendErr("[%d:%d] expected param func argument to be an integer but got %s", t.Start, t.End, argValTok.Literal)
|
|
continue
|
|
}
|
|
|
|
lastParamFunc.Args = append(lastParamFunc.Args, argVal)
|
|
case token.COMMA:
|
|
argValTok := p.l.NextToken()
|
|
argVal, err := parseParamFuncArg(argValTok)
|
|
if err != nil {
|
|
p.appendErr("[%d:%d] expected param func argument to be an integer but got %s", t.Start, t.End, argValTok.Literal)
|
|
continue
|
|
}
|
|
|
|
lastParamFunc.Args = append(lastParamFunc.Args, argVal)
|
|
case token.RPAREN:
|
|
stmt.Funcs = append(stmt.Funcs, lastParamFunc)
|
|
lastParamFunc = ast.ParamFunc{} // reset
|
|
case token.ELSE:
|
|
errCodeTok := p.l.NextToken()
|
|
if errCodeTok.Type != token.INT {
|
|
p.appendErr("[%d:%d] expected error code to be an integer but got %s", t.Start, t.End, errCodeTok.Literal)
|
|
continue
|
|
}
|
|
errCode, err := strconv.Atoi(errCodeTok.Literal)
|
|
if err != nil {
|
|
// this is a bug on lexer if throws because we already check for token.INT
|
|
p.appendErr("[%d:%d] unexpected lexer error while trying to convert error code to an integer, %s", t.Start, t.End, err.Error())
|
|
continue
|
|
}
|
|
stmt.ErrorCode = errCode
|
|
case token.RBRACE:
|
|
break
|
|
case token.ILLEGAL:
|
|
p.appendErr("[%d:%d] illegal token: %s", t.Start, t.End, t.Literal)
|
|
default:
|
|
p.appendErr("[%d:%d] unexpected token type: %q with value %s", t.Start, t.End, t.Type, t.Literal)
|
|
}
|
|
}
|
|
|
|
return stmt, p.Error()
|
|
}
|