Add way to specify token names

This commit is contained in:
Sasha Koshka 2024-07-28 02:29:49 -04:00
parent 6e7b41a996
commit ec0425ec60

View File

@ -8,6 +8,10 @@ type Parser struct {
// be set before use. // be set before use.
Lexer Lexer Lexer Lexer
// TokenNames assigns names to token kinds. This should be set before
// use.
TokenNames map[TokenKind] string
// Token is the current token the parser is operating on. // Token is the current token the parser is operating on.
Token Token Token Token
} }
@ -17,8 +21,8 @@ type Parser struct {
func (this *Parser) Expect (allowed ...TokenKind) error { func (this *Parser) Expect (allowed ...TokenKind) error {
if !this.Token.Is(allowed...) { if !this.Token.Is(allowed...) {
return Errorf ( return Errorf (
this.Token.Position, "unexpected %v; expected %s", this.Token.Position, "unexpected %s; expected %s",
this.Token, commaList(allowed...)) this.tokenName(this.Token.Kind), commaList(this.tokenNames(allowed...)...))
} }
return nil return nil
} }
@ -29,8 +33,8 @@ func (this *Parser) Expect (allowed ...TokenKind) error {
func (this *Parser) ExpectDesc (description string, allowed ...TokenKind) error { func (this *Parser) ExpectDesc (description string, allowed ...TokenKind) error {
if !this.Token.Is(allowed...) { if !this.Token.Is(allowed...) {
return Errorf ( return Errorf (
this.Token.Position, "unexpected %v; expected %s", this.Token.Position, "unexpected %s; expected %s",
this.Token, description) this.tokenName(this.Token.Kind), description)
} }
return nil return nil
} }
@ -54,8 +58,8 @@ func (this *Parser) ExpectNextDesc (description string, allowed ...TokenKind) er
func (this *Parser) ExpectValue (kind TokenKind, allowed ...string) error { func (this *Parser) ExpectValue (kind TokenKind, allowed ...string) error {
if !((this.Token.Is(kind) || kind == 0) && this.Token.ValueIs(allowed...)) { if !((this.Token.Is(kind) || kind == 0) && this.Token.ValueIs(allowed...)) {
return Errorf ( return Errorf (
this.Token.Position, "unexpected %v; expected %s", this.Token.Position, "unexpected %s; expected %s",
this.Token, commaList(allowed)) this.tokenName(this.Token.Kind), commaList(allowed))
} }
return nil return nil
} }
@ -65,8 +69,8 @@ func (this *Parser) ExpectValue (kind TokenKind, allowed ...string) error {
func (this *Parser) ExpectValueDesc (description string, kind TokenKind, allowed ...string) error { func (this *Parser) ExpectValueDesc (description string, kind TokenKind, allowed ...string) error {
if !this.Token.Is(kind) || !this.Token.ValueIs(allowed...) { if !this.Token.Is(kind) || !this.Token.ValueIs(allowed...) {
return Errorf ( return Errorf (
this.Token.Position, "unexpected %v; expected %s", this.Token.Position, "unexpected %s; expected %s",
this.Token, description) this.tokenName(this.Token.Kind), description)
} }
return nil return nil
} }
@ -110,6 +114,23 @@ func (this *Parser) EOF () bool {
return this.Token.EOF() return this.Token.EOF()
} }
func (this *Parser) tokenName (kind TokenKind) string {
if this.TokenNames != nil {
if name, ok := this.TokenNames[kind]; ok {
return name
}
}
return fmt.Sprintf("TokenKind(%d)", kind)
}
func (this *Parser) tokenNames (kinds ...TokenKind) []string {
names := make([]string, len(kinds))
for index, kind := range kinds {
names[index] = this.tokenName(kind)
}
return names
}
func commaList[ELEMENT any] (items ...ELEMENT) string { func commaList[ELEMENT any] (items ...ELEMENT) string {
list := "" list := ""