docs: saccharine expressions/stmts, private tokenIterator
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
package saccharine
|
|
||||||
|
|
||||||
type Expression interface {
|
|
||||||
expression()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
type Abstraction struct {
|
|
||||||
Parameters []string
|
|
||||||
Body Expression
|
|
||||||
}
|
|
||||||
|
|
||||||
type Application struct {
|
|
||||||
Abstraction Expression
|
|
||||||
Arguments []Expression
|
|
||||||
}
|
|
||||||
|
|
||||||
type Atom struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Clause struct {
|
|
||||||
Statements []Statement
|
|
||||||
Returns Expression
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Abstraction) expression() {}
|
|
||||||
func (Application) expression() {}
|
|
||||||
func (Atom) expression() {}
|
|
||||||
func (Clause) expression() {}
|
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
"git.maximhutz.com/max/lambda/pkg/iterator"
|
"git.maximhutz.com/max/lambda/pkg/iterator"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TokenIterator = iterator.Iterator[Token]
|
type tokenIterator = iterator.Iterator[Token]
|
||||||
|
|
||||||
func parseRawToken(i *TokenIterator, expected TokenType) (*Token, error) {
|
func parseRawToken(i *tokenIterator, expected TokenType) (*Token, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (*Token, error) {
|
return iterator.Do(i, func(i *tokenIterator) (*Token, error) {
|
||||||
if tok, err := i.Next(); err != nil {
|
if tok, err := i.Next(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if tok.Type != expected {
|
} else if tok.Type != expected {
|
||||||
@@ -21,7 +21,7 @@ func parseRawToken(i *TokenIterator, expected TokenType) (*Token, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func passSoftBreaks(i *TokenIterator) {
|
func passSoftBreaks(i *tokenIterator) {
|
||||||
for {
|
for {
|
||||||
if _, err := parseRawToken(i, TokenSoftBreak); err != nil {
|
if _, err := parseRawToken(i, TokenSoftBreak); err != nil {
|
||||||
return
|
return
|
||||||
@@ -29,8 +29,8 @@ func passSoftBreaks(i *TokenIterator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseToken(i *TokenIterator, expected TokenType, ignoreSoftBreaks bool) (*Token, error) {
|
func parseToken(i *tokenIterator, expected TokenType, ignoreSoftBreaks bool) (*Token, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (*Token, error) {
|
return iterator.Do(i, func(i *tokenIterator) (*Token, error) {
|
||||||
if ignoreSoftBreaks {
|
if ignoreSoftBreaks {
|
||||||
passSoftBreaks(i)
|
passSoftBreaks(i)
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ func parseToken(i *TokenIterator, expected TokenType, ignoreSoftBreaks bool) (*T
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseString(i *TokenIterator) (string, error) {
|
func parseString(i *tokenIterator) (string, error) {
|
||||||
if tok, err := parseToken(i, TokenAtom, true); err != nil {
|
if tok, err := parseToken(i, TokenAtom, true); err != nil {
|
||||||
return "", fmt.Errorf("no variable (col %d): %w", i.Index(), err)
|
return "", fmt.Errorf("no variable (col %d): %w", i.Index(), err)
|
||||||
} else {
|
} else {
|
||||||
@@ -47,7 +47,7 @@ func parseString(i *TokenIterator) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBreak(i *TokenIterator) (*Token, error) {
|
func parseBreak(i *tokenIterator) (*Token, error) {
|
||||||
if tok, softErr := parseRawToken(i, TokenSoftBreak); softErr == nil {
|
if tok, softErr := parseRawToken(i, TokenSoftBreak); softErr == nil {
|
||||||
return tok, nil
|
return tok, nil
|
||||||
} else if tok, hardErr := parseRawToken(i, TokenHardBreak); hardErr == nil {
|
} else if tok, hardErr := parseRawToken(i, TokenHardBreak); hardErr == nil {
|
||||||
@@ -57,7 +57,7 @@ func parseBreak(i *TokenIterator) (*Token, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseList[U any](i *TokenIterator, fn func(*TokenIterator) (U, error), minimum int) ([]U, error) {
|
func parseList[U any](i *tokenIterator, fn func(*tokenIterator) (U, error), minimum int) ([]U, error) {
|
||||||
results := []U{}
|
results := []U{}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -72,8 +72,8 @@ func parseList[U any](i *TokenIterator, fn func(*TokenIterator) (U, error), mini
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAbstraction(i *TokenIterator) (*Abstraction, error) {
|
func parseAbstraction(i *tokenIterator) (*Abstraction, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (*Abstraction, error) {
|
return iterator.Do(i, func(i *tokenIterator) (*Abstraction, error) {
|
||||||
if _, err := parseToken(i, TokenSlash, true); err != nil {
|
if _, err := parseToken(i, TokenSlash, true); err != nil {
|
||||||
return nil, fmt.Errorf("no function slash (col %d): %w", i.MustGet().Column, err)
|
return nil, fmt.Errorf("no function slash (col %d): %w", i.MustGet().Column, err)
|
||||||
} else if parameters, err := parseList(i, parseString, 0); err != nil {
|
} else if parameters, err := parseList(i, parseString, 0); err != nil {
|
||||||
@@ -88,8 +88,8 @@ func parseAbstraction(i *TokenIterator) (*Abstraction, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseApplication(i *TokenIterator) (*Application, error) {
|
func parseApplication(i *tokenIterator) (*Application, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (*Application, error) {
|
return iterator.Do(i, func(i *tokenIterator) (*Application, error) {
|
||||||
if _, err := parseToken(i, TokenOpenParen, true); err != nil {
|
if _, err := parseToken(i, TokenOpenParen, true); err != nil {
|
||||||
return nil, fmt.Errorf("no openning brackets (col %d): %w", i.MustGet().Column, err)
|
return nil, fmt.Errorf("no openning brackets (col %d): %w", i.MustGet().Column, err)
|
||||||
} else if expressions, err := parseList(i, parseExpression, 1); err != nil {
|
} else if expressions, err := parseList(i, parseExpression, 1); err != nil {
|
||||||
@@ -102,7 +102,7 @@ func parseApplication(i *TokenIterator) (*Application, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAtom(i *TokenIterator) (*Atom, error) {
|
func parseAtom(i *tokenIterator) (*Atom, error) {
|
||||||
if tok, err := parseToken(i, TokenAtom, true); err != nil {
|
if tok, err := parseToken(i, TokenAtom, true); err != nil {
|
||||||
return nil, fmt.Errorf("no variable (col %d): %w", i.Index(), err)
|
return nil, fmt.Errorf("no variable (col %d): %w", i.Index(), err)
|
||||||
} else {
|
} else {
|
||||||
@@ -110,7 +110,7 @@ func parseAtom(i *TokenIterator) (*Atom, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStatements(i *TokenIterator) ([]Statement, error) {
|
func parseStatements(i *tokenIterator) ([]Statement, error) {
|
||||||
statements := []Statement{}
|
statements := []Statement{}
|
||||||
|
|
||||||
//nolint:errcheck
|
//nolint:errcheck
|
||||||
@@ -129,7 +129,7 @@ func parseStatements(i *TokenIterator) ([]Statement, error) {
|
|||||||
return statements, nil
|
return statements, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseClause(i *TokenIterator, braces bool) (*Clause, error) {
|
func parseClause(i *tokenIterator, braces bool) (*Clause, error) {
|
||||||
if braces {
|
if braces {
|
||||||
if _, err := parseToken(i, TokenOpenBrace, true); err != nil {
|
if _, err := parseToken(i, TokenOpenBrace, true); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -158,8 +158,8 @@ func parseClause(i *TokenIterator, braces bool) (*Clause, error) {
|
|||||||
return &Clause{Statements: stmts[:len(stmts)-1], Returns: last.Value}, nil
|
return &Clause{Statements: stmts[:len(stmts)-1], Returns: last.Value}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseExpression(i *TokenIterator) (Expression, error) {
|
func parseExpression(i *tokenIterator) (Expression, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (Expression, error) {
|
return iterator.Do(i, func(i *tokenIterator) (Expression, error) {
|
||||||
passSoftBreaks(i)
|
passSoftBreaks(i)
|
||||||
|
|
||||||
switch peek := i.MustGet(); peek.Type {
|
switch peek := i.MustGet(); peek.Type {
|
||||||
@@ -177,8 +177,8 @@ func parseExpression(i *TokenIterator) (Expression, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLet(i *TokenIterator) (*LetStatement, error) {
|
func parseLet(i *tokenIterator) (*LetStatement, error) {
|
||||||
return iterator.Do(i, func(i *TokenIterator) (*LetStatement, error) {
|
return iterator.Do(i, func(i *tokenIterator) (*LetStatement, error) {
|
||||||
if parameters, err := parseList(i, parseString, 1); err != nil {
|
if parameters, err := parseList(i, parseString, 1); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if _, err := parseToken(i, TokenAssign, true); err != nil {
|
} else if _, err := parseToken(i, TokenAssign, true); err != nil {
|
||||||
@@ -191,7 +191,7 @@ func parseLet(i *TokenIterator) (*LetStatement, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDeclare(i *TokenIterator) (*DeclareStatement, error) {
|
func parseDeclare(i *tokenIterator) (*DeclareStatement, error) {
|
||||||
if value, err := parseExpression(i); err != nil {
|
if value, err := parseExpression(i); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +199,7 @@ func parseDeclare(i *TokenIterator) (*DeclareStatement, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStatement(i *TokenIterator) (Statement, error) {
|
func parseStatement(i *tokenIterator) (Statement, error) {
|
||||||
if let, letErr := parseLet(i); letErr == nil {
|
if let, letErr := parseLet(i); letErr == nil {
|
||||||
return let, nil
|
return let, nil
|
||||||
} else if declare, declErr := parseDeclare(i); declErr == nil {
|
} else if declare, declErr := parseDeclare(i); declErr == nil {
|
||||||
|
|||||||
60
pkg/saccharine/saccharine.go
Normal file
60
pkg/saccharine/saccharine.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Package saccharine defines the AST for the Saccharine language, a sugared
|
||||||
|
// lambda calculus with let bindings and multi-statement clauses.
|
||||||
|
package saccharine
|
||||||
|
|
||||||
|
// An Expression is a node in the Saccharine abstract syntax tree.
|
||||||
|
// It is a sealed interface; only types in this package may implement it.
|
||||||
|
type Expression interface {
|
||||||
|
expression()
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Abstraction is a lambda expression with zero or more parameters.
|
||||||
|
// A zero-parameter abstraction is treated as a thunk.
|
||||||
|
type Abstraction struct {
|
||||||
|
Parameters []string
|
||||||
|
Body Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Application applies an expression to zero or more arguments.
|
||||||
|
type Application struct {
|
||||||
|
Abstraction Expression
|
||||||
|
Arguments []Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Atom is a named variable.
|
||||||
|
type Atom struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Clause is a sequence of statements followed by a return expression.
|
||||||
|
type Clause struct {
|
||||||
|
Statements []Statement
|
||||||
|
Returns Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Abstraction) expression() {}
|
||||||
|
func (Application) expression() {}
|
||||||
|
func (Atom) expression() {}
|
||||||
|
func (Clause) expression() {}
|
||||||
|
|
||||||
|
// A Statement is a declaration within a Clause.
|
||||||
|
// It is a sealed interface; only types in this package may implement it.
|
||||||
|
type Statement interface {
|
||||||
|
statement()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A LetStatement binds a name (with optional parameters) to an expression.
|
||||||
|
type LetStatement struct {
|
||||||
|
Name string
|
||||||
|
Parameters []string
|
||||||
|
Body Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
// A DeclareStatement evaluates an expression for its side effects within a
|
||||||
|
// clause.
|
||||||
|
type DeclareStatement struct {
|
||||||
|
Value Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
func (LetStatement) statement() {}
|
||||||
|
func (DeclareStatement) statement() {}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package saccharine
|
|
||||||
|
|
||||||
type Statement interface {
|
|
||||||
statement()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
type LetStatement struct {
|
|
||||||
Name string
|
|
||||||
Parameters []string
|
|
||||||
Body Expression
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeclareStatement struct {
|
|
||||||
Value Expression
|
|
||||||
}
|
|
||||||
|
|
||||||
func (LetStatement) statement() {}
|
|
||||||
func (DeclareStatement) statement() {}
|
|
||||||
Reference in New Issue
Block a user