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()
|
||||
{
|
||||
return Choice(
|
||||
return Choice<LexicalToken, SyntaxNodeBase>(
|
||||
from variable in VariableParser()
|
||||
from _ in Operator(":=")
|
||||
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,
|
||||
Constant,
|
||||
VariableDeclaration,
|
||||
If,
|
||||
While,
|
||||
For,
|
||||
ProgramBody,
|
||||
ProgramHead,
|
||||
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;
|
||||
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)
|
||||
{
|
||||
ProgramParse(input);
|
||||
|
|
|
@ -15,6 +15,74 @@ public class StatementParserTests : GrammarParserTestBase
|
|||
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]
|
||||
[InlineData("""
|
||||
begin
|
||||
|
|
Loading…
Reference in New Issue
Block a user