Added lexing and parsing of LAMBDA to monkey3 version

main
oabrivard 2 years ago
parent f69fa28995
commit 879cf761bb

@ -281,6 +281,9 @@ func TestFunctionApplication(t *testing.T) {
{"let add = fn(x, y) { x + y; }; add(5, 5);", 10},
{"let add = fn(x, y) { x + y; }; add(5 + 5, add(5, 5));", 20},
{"fn(x) { x; }(5)", 5},
{"let add = fn(x, y) -> x + y; add(5 + 5, add(5, 5));", 20},
{"let sq = fn(a) -> a * a ; let dbl = fn(f,a) { f(a) * 2 }; dbl(sq,2);", 8},
{"let dbl = fn(f,a) { f(a) * 2 }; dbl(fn(a) -> a * a,2);", 8},
}
for _, tt := range tests {

@ -33,7 +33,14 @@ func (l *Lexer) NextToken() token.Token {
case '+':
tok = newToken(token.PLUS, l.ch)
case '-':
if l.peekChar() == '>' {
ch := l.ch
l.readChar()
literal := string(ch) + string(l.ch)
tok = token.Token{Type: token.LAMBDA, Literal: literal}
} else {
tok = newToken(token.MINUS, l.ch)
}
case '!':
if l.peekChar() == '=' {
ch := l.ch

@ -14,6 +14,8 @@ let add = fn(x, y) {
x + y;
};
let addlambda = fn(x,y) -> x + y;
let result = add(five, ten);
!-/*5;
5 < 10 > 5;
@ -59,6 +61,20 @@ if (5 < 10) {
{token.RBRACE, "}"},
{token.SEMICOLON, ";"},
{token.LET, "let"},
{token.IDENT, "addlambda"},
{token.ASSIGN, "="},
{token.FUNCTION, "fn"},
{token.LPAREN, "("},
{token.IDENT, "x"},
{token.COMMA, ","},
{token.IDENT, "y"},
{token.RPAREN, ")"},
{token.LAMBDA, "->"},
{token.IDENT, "x"},
{token.PLUS, "+"},
{token.IDENT, "y"},
{token.SEMICOLON, ";"},
{token.LET, "let"},
{token.IDENT, "result"},
{token.ASSIGN, "="},
{token.IDENT, "add"},

@ -357,11 +357,28 @@ func (p *Parser) parseFunctionLiteral() ast.Expression {
lit.Parameters = p.parseFunctionParameters()
if p.peekTokenIs(token.LAMBDA) {
// parse fn() with lambda syntax
p.nextToken()
p.nextToken()
block := &ast.BlockStatement{Token: p.curToken}
block.Statements = []ast.Statement{}
exp := p.parseExpressionStatement()
if exp != nil {
block.Statements = append(block.Statements, exp)
}
lit.Body = block
} else {
// parse fn() with bloc statement syntax
if !p.expectPeek(token.LBRACE) {
return nil
}
lit.Body = p.parseBlockStatement()
}
return lit
}

@ -503,15 +503,22 @@ func TestIfElseExpression(t *testing.T) {
}
func TestFunctionLiteralParsing(t *testing.T) {
input := `fn(x, y) { x + y; }`
tests := []struct {
input string
}{
{"fn(x, y) { x + y; }"},
{"fn(x, y) -> x + y;"},
}
l := lexer.New(input)
for _, tt := range tests {
l := lexer.New(tt.input)
p := New(l)
program := p.ParseProgram()
checkParserErrors(t, p)
if len(program.Statements) != 1 {
t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
t.Fatalf("program.Body does not contain %d statements. got=%d\n",
1, len(program.Statements))
}
@ -547,6 +554,7 @@ func TestFunctionLiteralParsing(t *testing.T) {
}
testInfixExpression(t, bodyStmt.Expression, "x", "+", "y")
}
}
func TestFunctionParameterParsing(t *testing.T) {

@ -33,6 +33,8 @@ const (
LBRACE = "{"
RBRACE = "}"
LAMBDA = "->"
// Keywords
FUNCTION = "FUNCTION"
LET = "LET"

Loading…
Cancel
Save