feat: error for when there is more source code than parsed
This commit is contained in:
@@ -25,7 +25,7 @@ func main() {
|
|||||||
cli.HandleError(err)
|
cli.HandleError(err)
|
||||||
|
|
||||||
// Parse tokens.
|
// Parse tokens.
|
||||||
tokens, err := saccharine.GetTokens([]rune(input))
|
tokens, err := saccharine.GetTokens(input)
|
||||||
cli.HandleError(err)
|
cli.HandleError(err)
|
||||||
logger.Info("parsed tokens", "tokens", tokens)
|
logger.Info("parsed tokens", "tokens", tokens)
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,15 @@ func (i Iterator[T]) Get() (T, error) {
|
|||||||
return i.items[i.index], nil
|
return i.items[i.index], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i Iterator[T]) MustGet() T {
|
||||||
|
var null T
|
||||||
|
if i.Done() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.items[i.index]
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new iterator, over a set of items.
|
// Create a new iterator, over a set of items.
|
||||||
func (i *Iterator[T]) Next() (T, error) {
|
func (i *Iterator[T]) Next() (T, error) {
|
||||||
item, err := i.Get()
|
item, err := i.Get()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func parseToken(i *TokenIterator, expected token.Type) (*token.Token, error) {
|
|||||||
if tok, err := i2.Next(); err != nil {
|
if tok, err := i2.Next(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if tok.Type != expected {
|
} else if tok.Type != expected {
|
||||||
return nil, fmt.Errorf("expected token, got %v'", tok.Value)
|
return nil, fmt.Errorf("expected token %v, got %v'", token.Name(expected), tok.Value)
|
||||||
} else {
|
} else {
|
||||||
i.Sync(i2)
|
i.Sync(i2)
|
||||||
return &tok, nil
|
return &tok, nil
|
||||||
@@ -56,11 +56,11 @@ func parseAbstraction(i *TokenIterator) (*ast.Abstraction, error) {
|
|||||||
i2 := i.Copy()
|
i2 := i.Copy()
|
||||||
|
|
||||||
if _, err := parseToken(i2, token.Slash); err != nil {
|
if _, err := parseToken(i2, token.Slash); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no function slash (col %d): %w", i2.MustGet().Index, err)
|
||||||
} else if parameters, err := parseParameters(i2); err != nil {
|
} else if parameters, err := parseParameters(i2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if _, err = parseToken(i2, token.Dot); err != nil {
|
} else if _, err = parseToken(i2, token.Dot); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no function dot (col %d): %w", i2.MustGet().Index, err)
|
||||||
} else if body, err := parseExpression(i2); err != nil {
|
} else if body, err := parseExpression(i2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
@@ -74,7 +74,7 @@ func parseApplication(i *TokenIterator) (*ast.Application, error) {
|
|||||||
expressions := []ast.Expression{}
|
expressions := []ast.Expression{}
|
||||||
|
|
||||||
if _, err := parseToken(i2, token.OpenParen); err != nil {
|
if _, err := parseToken(i2, token.OpenParen); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no openning brackets (col %d): %w", i2.MustGet().Index, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -86,7 +86,7 @@ func parseApplication(i *TokenIterator) (*ast.Application, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := parseToken(i2, token.CloseParen); err != nil {
|
if _, err := parseToken(i2, token.CloseParen); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no closing brackets (col %d): %w", i2.MustGet().Index, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(expressions) == 0 {
|
if len(expressions) == 0 {
|
||||||
@@ -99,12 +99,23 @@ func parseApplication(i *TokenIterator) (*ast.Application, error) {
|
|||||||
|
|
||||||
func parseAtom(i *TokenIterator) (*ast.Atom, error) {
|
func parseAtom(i *TokenIterator) (*ast.Atom, error) {
|
||||||
if tok, err := parseToken(i, token.Atom); err != nil {
|
if tok, err := parseToken(i, token.Atom); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("no variable (col %d): %w", i.Index(), err)
|
||||||
} else {
|
} else {
|
||||||
return ast.NewAtom(tok.Value), nil
|
return ast.NewAtom(tok.Value), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(i *TokenIterator) (ast.Expression, error) {
|
func Parse(tokens []token.Token) (ast.Expression, error) {
|
||||||
return parseExpression(i)
|
i := iterator.Of(tokens)
|
||||||
|
|
||||||
|
exp, err := parseExpression(i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !i.Done() {
|
||||||
|
return nil, fmt.Errorf("expected EOF, found more code (col %d)", i.MustGet().Index)
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,3 +45,24 @@ func NewSlash(index int) *Token {
|
|||||||
func NewAtom(name string, index int) *Token {
|
func NewAtom(name string, index int) *Token {
|
||||||
return &Token{Type: Atom, Index: index, Value: name}
|
return &Token{Type: Atom, Index: index, Value: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Name(typ Type) string {
|
||||||
|
switch typ {
|
||||||
|
case OpenParen:
|
||||||
|
return "("
|
||||||
|
case CloseParen:
|
||||||
|
return ")"
|
||||||
|
case Slash:
|
||||||
|
return "\\"
|
||||||
|
case Dot:
|
||||||
|
return "."
|
||||||
|
case Atom:
|
||||||
|
return "ATOM"
|
||||||
|
default:
|
||||||
|
return "?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Token) Name() string {
|
||||||
|
return Name(t.Type)
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ func getToken(i *iterator.Iterator[rune]) (*token.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parses a list of runes into tokens. All error encountered are returned, as well.
|
// Parses a list of runes into tokens. All error encountered are returned, as well.
|
||||||
func GetTokens(input []rune) (*iterator.Iterator[token.Token], error) {
|
func GetTokens(input string) ([]token.Token, error) {
|
||||||
i := iterator.Of(input)
|
i := iterator.Of([]rune(input))
|
||||||
tokens := []token.Token{}
|
tokens := []token.Token{}
|
||||||
errorList := []error{}
|
errorList := []error{}
|
||||||
|
|
||||||
@@ -84,5 +84,5 @@ func GetTokens(input []rune) (*iterator.Iterator[token.Token], error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return iterator.Of(tokens), errors.Join(errorList...)
|
return tokens, errors.Join(errorList...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
\n m.(m n)
|
\n m.(m n)
|
||||||
)
|
)
|
||||||
\m n f.(m (n f))
|
\m n f.(m (n f))
|
||||||
)
|
))
|
||||||
\n m.(m inc n)
|
\n m.(m inc n)
|
||||||
)
|
)
|
||||||
\n f x.(f (n f x))
|
\n f x.(f (n f x))
|
||||||
|
|||||||
Reference in New Issue
Block a user