Created
May 25, 2022 16:46
-
-
Save yuri4n/bf2d908371d4f1d7106d06659312480b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** This is basically The Lambda Calculus itself. This also forms our AST. | |
*/ | |
enum Expr: | |
case Application(lhs: Expr, rhs: Expr) | |
case Function(param: Token.Identifier, body: Expr) | |
case Atom(identifier: Token.Identifier) | |
/** Characters that make our syntax, e.g. (λx.x λx.x) λy.y | |
*/ | |
enum Token: | |
case Lambda | |
case Dot | |
case LParenthesis, RParenthesis | |
case Identifier(value: String) | |
case WhiteSpace | |
// 1: Added after syntax sugar was explained. | |
case Keyword(value: Token.Kwd) | |
case Equal | |
// end 1. | |
object Token: | |
type Kwd = "def" | |
def create(token: Char | String): Either[Throwable, Token] = token match | |
case '\\' | `lambdaSymbol` => Right(Lambda) | |
case '.' => Right(Dot) | |
case '(' => Right(LParenthesis) | |
case ')' => Right(RParenthesis) | |
case ' ' => Right(Token.WhiteSpace) | |
// 1: Added after syntax sugar was explained. | |
case '=' => Right(Token.Equal) | |
case keyword: Kwd => Right(Token.Keyword(keyword)) | |
// end 1. | |
case name: String if "[a-z]\\w*".r.matches(name) => | |
Right(Token.Identifier(name)) | |
case ut => Left(new Throwable(s"[Unexpected Token] $ut")) | |
extension (s: Char | String) def toToken: Either[Throwable, Token] = Token.create(s) | |
// From here we would like to extend our tokens to include definitions as part of our language. | |
def lexer(expr: String): Either[Throwable, Seq[Token]] = | |
@tailrec def recursiveLexer( | |
exprRes: String, | |
res: Either[Throwable, Seq[Token]] | |
): Either[Throwable, Seq[Token]] = if exprRes.isBlank then res | |
else | |
val head = exprRes.head | |
val seq: Char | String = | |
if head.isLower && head != lambdaSymbol then exprRes.takeWhile(c => c.isLetterOrDigit || c == '_') | |
else head | |
val dropN = seq match | |
case _: Char => 1 | |
case s: String => s.length | |
seq.toToken match | |
case Right(token) => | |
recursiveLexer(exprRes.drop(dropN), res.map(r => r :+ token)) | |
case _ => recursiveLexer(exprRes.drop(dropN), res) | |
recursiveLexer(expr, Right(Seq.empty)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment