added variables and producer check
This commit is contained in:
@@ -125,3 +125,21 @@ type Pragma struct {
|
||||
}
|
||||
|
||||
func (p *Pragma) Pos() Position { return p.Position }
|
||||
|
||||
type VariableDefinition struct {
|
||||
Position Position
|
||||
Name string
|
||||
TypeExpr string
|
||||
DefaultValue Value
|
||||
}
|
||||
|
||||
func (v *VariableDefinition) Pos() Position { return v.Position }
|
||||
func (v *VariableDefinition) isDefinition() {}
|
||||
|
||||
type VariableReferenceValue struct {
|
||||
Position Position
|
||||
Name string
|
||||
}
|
||||
|
||||
func (v *VariableReferenceValue) Pos() Position { return v.Position }
|
||||
func (v *VariableReferenceValue) isValue() {}
|
||||
|
||||
@@ -23,6 +23,11 @@ const (
|
||||
TokenComment
|
||||
TokenDocstring
|
||||
TokenComma
|
||||
TokenColon
|
||||
TokenPipe
|
||||
TokenLBracket
|
||||
TokenRBracket
|
||||
TokenSymbol
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
@@ -124,6 +129,16 @@ func (l *Lexer) NextToken() Token {
|
||||
return l.emit(TokenRBrace)
|
||||
case ',':
|
||||
return l.emit(TokenComma)
|
||||
case ':':
|
||||
return l.emit(TokenColon)
|
||||
case '|':
|
||||
return l.emit(TokenPipe)
|
||||
case '[':
|
||||
return l.emit(TokenLBracket)
|
||||
case ']':
|
||||
return l.emit(TokenRBracket)
|
||||
case '&', '?', '!', '<', '>', '*', '(', ')':
|
||||
return l.emit(TokenSymbol)
|
||||
case '"':
|
||||
return l.lexString()
|
||||
case '/':
|
||||
@@ -151,7 +166,7 @@ func (l *Lexer) NextToken() Token {
|
||||
func (l *Lexer) lexIdentifier() Token {
|
||||
for {
|
||||
r := l.next()
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == ':' {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' {
|
||||
continue
|
||||
}
|
||||
l.backup()
|
||||
@@ -247,7 +262,7 @@ func (l *Lexer) lexHashIdentifier() Token {
|
||||
// We are at '#', l.start is just before it
|
||||
for {
|
||||
r := l.next()
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == ':' || r == '#' {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.' || r == '#' {
|
||||
continue
|
||||
}
|
||||
l.backup()
|
||||
|
||||
@@ -101,6 +101,9 @@ func (p *Parser) parseDefinition() (Definition, bool) {
|
||||
switch tok.Type {
|
||||
case TokenIdentifier:
|
||||
name := tok.Value
|
||||
if name == "#var" {
|
||||
return p.parseVariableDefinition(tok)
|
||||
}
|
||||
if p.peek().Type != TokenEqual {
|
||||
p.addError(tok.Position, "expected =")
|
||||
return nil, false
|
||||
@@ -244,6 +247,8 @@ func (p *Parser) parseValue() (Value, bool) {
|
||||
true
|
||||
case TokenIdentifier:
|
||||
return &ReferenceValue{Position: tok.Position, Value: tok.Value}, true
|
||||
case TokenObjectIdentifier:
|
||||
return &VariableReferenceValue{Position: tok.Position, Name: tok.Value}, true
|
||||
case TokenLBrace:
|
||||
arr := &ArrayValue{Position: tok.Position}
|
||||
for {
|
||||
@@ -269,3 +274,53 @@ func (p *Parser) parseValue() (Value, bool) {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseVariableDefinition(startTok Token) (Definition, bool) {
|
||||
nameTok := p.next()
|
||||
if nameTok.Type != TokenIdentifier {
|
||||
p.addError(nameTok.Position, "expected variable name")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if p.next().Type != TokenColon {
|
||||
p.addError(nameTok.Position, "expected :")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var typeTokens []Token
|
||||
startLine := nameTok.Position.Line
|
||||
|
||||
for {
|
||||
t := p.peek()
|
||||
if t.Position.Line > startLine || t.Type == TokenEOF {
|
||||
break
|
||||
}
|
||||
if t.Type == TokenEqual {
|
||||
break
|
||||
}
|
||||
typeTokens = append(typeTokens, p.next())
|
||||
}
|
||||
|
||||
typeExpr := ""
|
||||
for _, t := range typeTokens {
|
||||
typeExpr += t.Value + " "
|
||||
}
|
||||
|
||||
var defVal Value
|
||||
if p.peek().Type == TokenEqual {
|
||||
p.next()
|
||||
val, ok := p.parseValue()
|
||||
if ok {
|
||||
defVal = val
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
return &VariableDefinition{
|
||||
Position: startTok.Position,
|
||||
Name: nameTok.Value,
|
||||
TypeExpr: strings.TrimSpace(typeExpr),
|
||||
DefaultValue: defVal,
|
||||
}, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user