Implemented operators and better indexing
This commit is contained in:
@@ -143,3 +143,13 @@ type VariableReferenceValue struct {
|
||||
|
||||
func (v *VariableReferenceValue) Pos() Position { return v.Position }
|
||||
func (v *VariableReferenceValue) isValue() {}
|
||||
|
||||
type BinaryExpression struct {
|
||||
Position Position
|
||||
Left Value
|
||||
Operator Token
|
||||
Right Value
|
||||
}
|
||||
|
||||
func (b *BinaryExpression) Pos() Position { return b.Position }
|
||||
func (b *BinaryExpression) isValue() {}
|
||||
|
||||
@@ -28,6 +28,14 @@ const (
|
||||
TokenLBracket
|
||||
TokenRBracket
|
||||
TokenSymbol
|
||||
TokenPlus
|
||||
TokenMinus
|
||||
TokenStar
|
||||
TokenSlash
|
||||
TokenPercent
|
||||
TokenCaret
|
||||
TokenAmpersand
|
||||
TokenConcat
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
@@ -137,16 +145,45 @@ func (l *Lexer) NextToken() Token {
|
||||
return l.emit(TokenLBracket)
|
||||
case ']':
|
||||
return l.emit(TokenRBracket)
|
||||
case '&', '?', '!', '<', '>', '*', '(', ')', '~', '%', '^':
|
||||
case '+':
|
||||
if unicode.IsSpace(l.peek()) {
|
||||
return l.emit(TokenPlus)
|
||||
}
|
||||
return l.lexObjectIdentifier()
|
||||
case '-':
|
||||
if unicode.IsDigit(l.peek()) {
|
||||
return l.lexNumber()
|
||||
}
|
||||
if unicode.IsSpace(l.peek()) {
|
||||
return l.emit(TokenMinus)
|
||||
}
|
||||
return l.lexIdentifier()
|
||||
case '*':
|
||||
return l.emit(TokenStar)
|
||||
case '/':
|
||||
p := l.peek()
|
||||
if p == '/' || p == '*' || p == '#' || p == '!' {
|
||||
return l.lexComment()
|
||||
}
|
||||
return l.emit(TokenSlash)
|
||||
case '%':
|
||||
return l.emit(TokenPercent)
|
||||
case '^':
|
||||
return l.emit(TokenCaret)
|
||||
case '&':
|
||||
return l.emit(TokenAmpersand)
|
||||
case '.':
|
||||
if l.peek() == '.' {
|
||||
l.next()
|
||||
return l.emit(TokenConcat)
|
||||
}
|
||||
return l.emit(TokenSymbol)
|
||||
case '~', '!', '<', '>', '(', ')', '?', '\\':
|
||||
return l.emit(TokenSymbol)
|
||||
case '"':
|
||||
return l.lexString()
|
||||
case '/':
|
||||
return l.lexComment()
|
||||
case '#':
|
||||
return l.lexHashIdentifier()
|
||||
case '+':
|
||||
fallthrough
|
||||
case '$':
|
||||
return l.lexObjectIdentifier()
|
||||
}
|
||||
|
||||
@@ -226,6 +226,56 @@ func (p *Parser) parseSubnode() (Subnode, bool) {
|
||||
}
|
||||
|
||||
func (p *Parser) parseValue() (Value, bool) {
|
||||
return p.parseExpression(0)
|
||||
}
|
||||
|
||||
func getPrecedence(t TokenType) int {
|
||||
switch t {
|
||||
case TokenStar, TokenSlash, TokenPercent:
|
||||
return 5
|
||||
case TokenPlus, TokenMinus:
|
||||
return 4
|
||||
case TokenConcat:
|
||||
return 3
|
||||
case TokenAmpersand:
|
||||
return 2
|
||||
case TokenPipe, TokenCaret:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseExpression(minPrecedence int) (Value, bool) {
|
||||
left, ok := p.parseAtom()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
for {
|
||||
t := p.peek()
|
||||
prec := getPrecedence(t.Type)
|
||||
if prec == 0 || prec <= minPrecedence {
|
||||
break
|
||||
}
|
||||
p.next()
|
||||
|
||||
right, ok := p.parseExpression(prec)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
left = &BinaryExpression{
|
||||
Position: left.Pos(),
|
||||
Left: left,
|
||||
Operator: t,
|
||||
Right: right,
|
||||
}
|
||||
}
|
||||
return left, true
|
||||
}
|
||||
|
||||
func (p *Parser) parseAtom() (Value, bool) {
|
||||
tok := p.next()
|
||||
switch tok.Type {
|
||||
case TokenString:
|
||||
|
||||
Reference in New Issue
Block a user