Parsing functions *always* begin on current token, leave trailing one

This commit is contained in:
Sasha Koshka 2024-02-06 16:22:49 -05:00
parent 1b50c8f879
commit bca9de4106
2 changed files with 46 additions and 36 deletions

View File

@ -31,31 +31,41 @@ func (this *Parser) ParseInto (tree *Tree) error {
return err
}
// expect gets the next token if it matches a list of token kind(s), else it
// returns an error describing what it expected.
func (this *Parser) expect (allowed ...lexer.TokenKind) (lexer.Token, error) {
token, err := this.next()
if err != nil { return lexer.Token { }, err }
if !token.Is(allowed...) {
return lexer.Token { }, errors.Errorf (
token.Position, "expected %s",
// expect checks the current token to see if it matches a list of token kind(s),
// else it returns an error describing what it expected.
func (this *Parser) expect (allowed ...lexer.TokenKind) error {
if !this.token.Is(allowed...) {
return errors.Errorf (
this.token.Position, "expected %s",
commaList(allowed...))
}
return token, nil
return nil
}
// expectDesc is like expect, but the expected entitie(s) are described
// manually. This can be helpful when a large syntactical entity is expected and
// the first token(s) of it offer insufficient information.
func (this *Parser) expectDesc (description string, allowed ...lexer.TokenKind) (lexer.Token, error) {
token, err := this.next()
if err != nil { return lexer.Token { }, err }
if !token.Is(allowed...) {
return lexer.Token { }, errors.Errorf (
token.Position, "expected %s",
func (this *Parser) expectDesc (description string, allowed ...lexer.TokenKind) error {
if !this.token.Is(allowed...) {
return errors.Errorf (
this.token.Position, "expected %s",
description)
}
return token, nil
return nil
}
// expectNext is like expect, but gets the next token first.
func (this *Parser) expectNext (allowed ...lexer.TokenKind) error {
err := this.next()
if err != nil { return err }
return this.expect(allowed...)
}
// expectNextDesc is like expectDesc, but gets the next token first.
func (this *Parser) expectNextDesc (description string, allowed ...lexer.TokenKind) error {
err := this.next()
if err != nil { return err }
return this.expectDesc(description, allowed...)
}
// expectValue returns an error if the current token's value does not match the
@ -80,20 +90,22 @@ func (this *Parser) expectValueDesc (description string, kind lexer.TokenKind, a
return nil
}
func (this *Parser) next () (lexer.Token, error) {
func (this *Parser) next () error {
token, err := this.lexer.Next()
if err != nil { return token, err }
if err != nil { return err }
this.token = token
return token, nil
return nil
}
func (this *Parser) parse () error {
err := this.next()
if err != nil { return err }
for {
token, err := this.expectDesc (
err = this.expectDesc (
descriptionTopLevel,
startTokensTopLevel...)
if err != nil { return err }
if token.EOF() { return nil }
if this.token.EOF() { return nil }
err = this.parseTopLevel()
if err != nil { return err }

View File

@ -13,14 +13,12 @@ var startTokensTopLevel = []lexer.TokenKind {
}
func (this *Parser) parseTopLevel () error {
var err error
var token lexer.Token
var err error
access := entity.AccessPrivate
if this.token.Kind == lexer.Symbol {
access, err = this.parseAccess()
token, err = this.expectDesc (
err = this.expectNextDesc (
descriptionTopLevel,
lexer.Symbol,
lexer.LBracket,
@ -39,20 +37,20 @@ func (this *Parser) parseTopLevel () error {
// TypeIdent: Method, or Typedef
typeName := this.token.Value
token, err = this.expect(lexer.Dot, lexer.Colon)
err = this.expectNext(lexer.Dot, lexer.Colon)
if err != nil { return err }
switch token.Kind {
switch this.token.Kind {
case lexer.Dot:
// Dot: Method
_, err = this.expectDesc(descriptionSignature, startTokensSignature...)
err = this.expectNextDesc(descriptionSignature, startTokensSignature...)
if err != nil { return err }
method, err := this.parseMethod(access, typeName)
if err != nil { return err }
this.tree.AddDeclaration(method)
case lexer.Colon:
// Colon: Typedef
_, err = this.expect(startTokensType...)
err = this.expectNext(startTokensType...)
if err != nil { return err }
typedef, err := this.parseTypedef(access, typeName)
if err != nil { return err }
@ -81,21 +79,21 @@ func (this *Parser) parseFunction (access entity.Access) (*entity.Function, erro
Signature: signature,
}
token, err := this.expectDesc (
err = this.expectNextDesc (
"Function body, Link name, " + descriptionTopLevel,
appendCopy(startTokensTopLevel, lexer.Symbol, lexer.String)...)
if err != nil { return nil, err }
if token.Is(lexer.String) {
if this.token.Is(lexer.String) {
// String: Link name
function.LinkName = token.Value
token, err = this.expectDesc (
function.LinkName = this.token.Value
err = this.expectNextDesc (
"Function body, " + descriptionTopLevel,
appendCopy(startTokensTopLevel, lexer.Symbol)...)
if err != nil { return nil, err }
}
if token.Is(startTokensTopLevel...) {
if this.token.Is(startTokensTopLevel...) {
// startTokensTopLevel: function has no body and is finished,
// move on to next top level declaration or graceful EOF.
return function, nil
@ -106,7 +104,7 @@ func (this *Parser) parseFunction (access entity.Access) (*entity.Function, erro
if err != nil { return nil, err }
// Expression
_, err = this.expectDesc(descriptionExpression, startTokensExpression...)
err = this.expectNextDesc(descriptionExpression, startTokensExpression...)
if err != nil { return nil, err }
bodyExpression, err := this.parseExpression()
if err != nil { return nil, err }
@ -127,5 +125,5 @@ func (this *Parser) parseMethod (access entity.Access, typeName string) (*entity
}
func (this *Parser) parseTypedef (access entity.Access, typeName string) (*entity.Typedef, error) {
// TODO
}