Parse lambda expressions

This commit is contained in:
Alexander Luzgarev 2018-04-01 19:24:46 +02:00
parent efbecd67d9
commit d359527cf8
4 changed files with 76 additions and 10 deletions

View File

@ -356,9 +356,23 @@ namespace Parser.Tests
var text = "@sqrt"; var text = "@sqrt";
var sut = CreateParser(text); var sut = CreateParser(text);
var actual = sut.ParseExpression(); var actual = sut.ParseExpression();
Assert.IsInstanceOf<FunctionHandleNode>(actual); Assert.IsInstanceOf<NamedFunctionHandleNode>(actual);
var f = (FunctionHandleNode) actual; var f = (NamedFunctionHandleNode) actual;
Assert.AreEqual("sqrt", f.IdentifierName.Token.PureToken.LiteralText); Assert.AreEqual("sqrt", f.IdentifierName.Token.PureToken.LiteralText);
Assert.AreEqual(text, actual.FullText);
}
[Test]
public void ParseLambda()
{
var text = "@(x, y) x + y";
var sut = CreateParser(text);
var actual = sut.ParseExpression();
Assert.IsInstanceOf<LambdaNode>(actual);
var f = (LambdaNode) actual;
Assert.AreEqual(2, f.Input.Parameters.Parameters.Count);
Assert.IsInstanceOf<BinaryOperationExpressionNode>(f.Body);
Assert.AreEqual(text, actual.FullText);
} }
} }
} }

View File

@ -553,10 +553,19 @@ namespace Parser
private FunctionHandleNode ParseFunctionHandle() private FunctionHandleNode ParseFunctionHandle()
{ {
var atSign = EatToken(); var atSign = EatToken();
var identifierName = EatToken(TokenKind.Identifier); if (CurrentToken.Kind == TokenKind.Identifier)
return Factory.FunctionHandle( {
Factory.Token(atSign), var identifierName = EatToken(TokenKind.Identifier);
Factory.IdentifierName(identifierName)); return Factory.NamedFunctionHandle(
Factory.Token(atSign),
Factory.IdentifierName(identifierName));
} else if (CurrentToken.Kind == TokenKind.OpeningBracket)
{
var inputs = ParseFunctionInputDescription();
var body = ParseExpression();
return Factory.Lambda(Factory.Token(atSign), inputs, body);
}
throw new ParsingException($"Unexpected token {CurrentToken.PureToken} while parsing function handle at {CurrentToken.PureToken.Position}.");
} }
private ExpressionNode ParseSubExpression(ParseOptions options, Precedence precedence) private ExpressionNode ParseSubExpression(ParseOptions options, Precedence precedence)

View File

@ -542,7 +542,7 @@ namespace Parser
return result; return result;
} }
public FunctionHandleNode FunctionHandle( public NamedFunctionHandleNode NamedFunctionHandle(
TokenNode atSign, TokenNode atSign,
IdentifierNameNode identifierName) IdentifierNameNode identifierName)
{ {
@ -551,7 +551,7 @@ namespace Parser
atSign, atSign,
identifierName identifierName
}; };
var result = new FunctionHandleNode( var result = new NamedFunctionHandleNode(
children, children,
atSign, atSign,
identifierName); identifierName);
@ -559,5 +559,24 @@ namespace Parser
return result; return result;
} }
public LambdaNode Lambda(
TokenNode atSign,
FunctionInputDescriptionNode input,
ExpressionNode body)
{
var children = new List<SyntaxNode>
{
atSign,
input,
body
};
var result = new LambdaNode(
children,
atSign,
input,
body);
SetParent(result);
return result;
}
} }
} }

View File

@ -587,12 +587,20 @@ namespace Parser
} }
} }
public class FunctionHandleNode : ExpressionNode public abstract class FunctionHandleNode : ExpressionNode
{
protected FunctionHandleNode(
List<SyntaxNode> children) : base(children)
{
}
}
public class NamedFunctionHandleNode : FunctionHandleNode
{ {
public TokenNode AtSign { get; } public TokenNode AtSign { get; }
public IdentifierNameNode IdentifierName { get; } public IdentifierNameNode IdentifierName { get; }
public FunctionHandleNode( public NamedFunctionHandleNode(
List<SyntaxNode> children, List<SyntaxNode> children,
TokenNode atSign, TokenNode atSign,
IdentifierNameNode identifierName) : base(children) IdentifierNameNode identifierName) : base(children)
@ -602,5 +610,21 @@ namespace Parser
} }
} }
public class LambdaNode : FunctionHandleNode
{
public TokenNode AtSign { get; }
public FunctionInputDescriptionNode Input { get; }
public ExpressionNode Body { get; }
public LambdaNode(
List<SyntaxNode> children,
TokenNode atSign,
FunctionInputDescriptionNode input,
ExpressionNode body) : base(children)
{
AtSign = atSign;
Input = input;
Body = body;
}
}
} }