add: for & if & while support.
This commit is contained in:
parent
97f9fb9ec3
commit
c44b720e09
|
@ -150,13 +150,56 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, IfNode> IfParser()
|
||||||
|
{
|
||||||
|
IParser<LexicalToken, IfNode> commonPart = from _ in Keyword("if")
|
||||||
|
from condition in ExpressionParser()
|
||||||
|
from _1 in Keyword("then")
|
||||||
|
from statement in StatementParser()
|
||||||
|
select new IfNode(condition, statement);
|
||||||
|
|
||||||
|
return Choice(
|
||||||
|
from common in commonPart
|
||||||
|
from _ in Keyword("else")
|
||||||
|
from elseStatement in StatementParser()
|
||||||
|
select new IfNode(common.Condition, common.Statement, elseStatement),
|
||||||
|
commonPart
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, ForNode> ForParser()
|
||||||
|
{
|
||||||
|
return from _ in Keyword("for")
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
from _1 in Operator(":=")
|
||||||
|
from left in ExpressionParser()
|
||||||
|
from _2 in Keyword("to")
|
||||||
|
from right in ExpressionParser()
|
||||||
|
from _3 in Keyword("do")
|
||||||
|
from statement in StatementParser()
|
||||||
|
select new ForNode(identifier, left, right, statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, WhileNode> WhileParser()
|
||||||
|
{
|
||||||
|
return from _ in Keyword("while")
|
||||||
|
from condition in ExpressionParser()
|
||||||
|
from _1 in Keyword("do")
|
||||||
|
from statement in StatementParser()
|
||||||
|
select new WhileNode(condition, statement);
|
||||||
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
||||||
{
|
{
|
||||||
return Choice(
|
return Choice<LexicalToken, SyntaxNodeBase>(
|
||||||
from variable in VariableParser()
|
from variable in VariableParser()
|
||||||
from _ in Operator(":=")
|
from _ in Operator(":=")
|
||||||
from expression in ExpressionParser()
|
from expression in ExpressionParser()
|
||||||
select new AssignNode(variable, expression)
|
select new AssignNode(variable, expression),
|
||||||
|
IfParser(),
|
||||||
|
ForParser(),
|
||||||
|
WhileParser(),
|
||||||
|
CompoundStatementParser()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
CanonSharp.Pascal/SyntaxTree/ForNode.cs
Normal file
20
CanonSharp.Pascal/SyntaxTree/ForNode.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using CanonSharp.Pascal.Scanner;
|
||||||
|
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class ForNode(
|
||||||
|
LexicalToken identifier,
|
||||||
|
SyntaxNodeBase leftCondition,
|
||||||
|
SyntaxNodeBase rightCondition,
|
||||||
|
SyntaxNodeBase statement) : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.For;
|
||||||
|
|
||||||
|
public LexicalToken Identifier => identifier;
|
||||||
|
|
||||||
|
public SyntaxNodeBase LeftCondition => leftCondition;
|
||||||
|
|
||||||
|
public SyntaxNodeBase RightCondition => rightCondition;
|
||||||
|
|
||||||
|
public SyntaxNodeBase Statement => statement;
|
||||||
|
}
|
26
CanonSharp.Pascal/SyntaxTree/IfNode.cs
Normal file
26
CanonSharp.Pascal/SyntaxTree/IfNode.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class IfNode : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.If;
|
||||||
|
|
||||||
|
public SyntaxNodeBase Condition { get; }
|
||||||
|
|
||||||
|
public SyntaxNodeBase Statement { get; }
|
||||||
|
|
||||||
|
public SyntaxNodeBase? ElseStatement { get; }
|
||||||
|
|
||||||
|
public IfNode(SyntaxNodeBase condition, SyntaxNodeBase statement)
|
||||||
|
{
|
||||||
|
Condition = condition;
|
||||||
|
Statement = statement;
|
||||||
|
ElseStatement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfNode(SyntaxNodeBase condition, SyntaxNodeBase statement, SyntaxNodeBase elseStatement)
|
||||||
|
{
|
||||||
|
Condition = condition;
|
||||||
|
Statement = statement;
|
||||||
|
ElseStatement = elseStatement;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,9 @@ public enum SyntaxNodeType
|
||||||
Block,
|
Block,
|
||||||
Constant,
|
Constant,
|
||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
|
If,
|
||||||
|
While,
|
||||||
|
For,
|
||||||
ProgramBody,
|
ProgramBody,
|
||||||
ProgramHead,
|
ProgramHead,
|
||||||
Program
|
Program
|
||||||
|
|
10
CanonSharp.Pascal/SyntaxTree/WhileNode.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/WhileNode.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class WhileNode(SyntaxNodeBase condition, SyntaxNodeBase statement) : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.While;
|
||||||
|
|
||||||
|
public SyntaxNodeBase Condition => condition;
|
||||||
|
|
||||||
|
public SyntaxNodeBase Statement => statement;
|
||||||
|
}
|
|
@ -138,6 +138,21 @@ public class ProgramParserTests : GrammarParserTestBase
|
||||||
a[10,0] := 1;
|
a[10,0] := 1;
|
||||||
end.
|
end.
|
||||||
""")]
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
var i : integer;
|
||||||
|
begin
|
||||||
|
while i < 10 do
|
||||||
|
i := i + 1;
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
public void ProgramParseTest(string input)
|
public void ProgramParseTest(string input)
|
||||||
{
|
{
|
||||||
ProgramParse(input);
|
ProgramParse(input);
|
||||||
|
|
|
@ -15,6 +15,74 @@ public class StatementParserTests : GrammarParserTestBase
|
||||||
Assert.Equal(1, node.Expression.Convert<IntegerValueNode>().Value);
|
Assert.Equal(1, node.Expression.Convert<IntegerValueNode>().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IfTest1()
|
||||||
|
{
|
||||||
|
IfNode node = RunParser<IfNode>(GrammarParser.IfParser(), """
|
||||||
|
if i = 1 then
|
||||||
|
a := a + 1
|
||||||
|
else
|
||||||
|
a := a + 2
|
||||||
|
""");
|
||||||
|
Assert.NotNull(node.ElseStatement);
|
||||||
|
|
||||||
|
BinaryOperatorNode condition = node.Condition.Convert<BinaryOperatorNode>();
|
||||||
|
Assert.Equal(BinaryOperatorType.Equal, condition.OperatorType);
|
||||||
|
|
||||||
|
AssignNode statement = node.Statement.Convert<AssignNode>();
|
||||||
|
Assert.Equal("a", statement.Variable.Identifier.LiteralValue);
|
||||||
|
|
||||||
|
AssignNode elseStatement = node.Statement.Convert<AssignNode>();
|
||||||
|
Assert.Equal("a", elseStatement.Variable.Identifier.LiteralValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IfTest2()
|
||||||
|
{
|
||||||
|
IfNode node = RunParser<IfNode>(GrammarParser.IfParser(), """
|
||||||
|
if i = 1 then
|
||||||
|
if i = 2 then
|
||||||
|
a := a + 1
|
||||||
|
else
|
||||||
|
a := a + 2
|
||||||
|
""");
|
||||||
|
|
||||||
|
Assert.Null(node.ElseStatement);
|
||||||
|
|
||||||
|
IfNode subIfNode = node.Statement.Convert<IfNode>();
|
||||||
|
Assert.NotNull(subIfNode.ElseStatement);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ForTest1()
|
||||||
|
{
|
||||||
|
ForNode node = RunParser<ForNode>(GrammarParser.ForParser(), """
|
||||||
|
for i := 1 to 10 do
|
||||||
|
a := a + i
|
||||||
|
""");
|
||||||
|
Assert.Equal("i", node.Identifier.LiteralValue);
|
||||||
|
Assert.Equal(1, node.LeftCondition.Convert<IntegerValueNode>().Value);
|
||||||
|
Assert.Equal(10, node.RightCondition.Convert<IntegerValueNode>().Value);
|
||||||
|
|
||||||
|
AssignNode assignNode = node.Statement.Convert<AssignNode>();
|
||||||
|
Assert.Equal("a", assignNode.Variable.Identifier.LiteralValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WhileTest1()
|
||||||
|
{
|
||||||
|
WhileNode node = RunParser<WhileNode>(GrammarParser.WhileParser(), """
|
||||||
|
while c >= 1 do
|
||||||
|
a := a + 1;
|
||||||
|
""");
|
||||||
|
|
||||||
|
BinaryOperatorNode binaryOperatorNode = node.Condition.Convert<BinaryOperatorNode>();
|
||||||
|
Assert.Equal(BinaryOperatorType.GreaterEqual, binaryOperatorNode.OperatorType);
|
||||||
|
|
||||||
|
AssignNode assignNode = node.Statement.Convert<AssignNode>();
|
||||||
|
Assert.Equal("a", assignNode.Variable.Identifier.LiteralValue);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("""
|
[InlineData("""
|
||||||
begin
|
begin
|
||||||
|
|
Loading…
Reference in New Issue
Block a user