added variables and producer check

This commit is contained in:
Martino Ferrari
2026-01-28 17:50:49 +01:00
parent 8811ac9273
commit 03fe7d33b0
11 changed files with 413 additions and 48 deletions

View File

@@ -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() {}

View File

@@ -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()

View File

@@ -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
}