add: Subprogram declarations and procedure call support.
This commit is contained in:
parent
c44b720e09
commit
5acae7d489
|
@ -32,6 +32,13 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
from _2 in Delimiter(")")
|
from _2 in Delimiter(")")
|
||||||
select node;
|
select node;
|
||||||
|
|
||||||
|
IParser<LexicalToken, SyntaxNodeBase> procedureCallParser =
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
from _ in Delimiter("(")
|
||||||
|
from expressions in ExpressionParser().SeparatedBy(Delimiter(","))
|
||||||
|
from _1 in Delimiter(")")
|
||||||
|
select new ProcedureCallNode(identifier, expressions);
|
||||||
|
|
||||||
return Choice(
|
return Choice(
|
||||||
TrueParser(),
|
TrueParser(),
|
||||||
FalseParser(),
|
FalseParser(),
|
||||||
|
@ -39,6 +46,7 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
minusParser,
|
minusParser,
|
||||||
plusParser,
|
plusParser,
|
||||||
notParser,
|
notParser,
|
||||||
|
procedureCallParser,
|
||||||
VariableParser(),
|
VariableParser(),
|
||||||
parenthesisParser
|
parenthesisParser
|
||||||
);
|
);
|
||||||
|
@ -189,6 +197,19 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
select new WhileNode(condition, statement);
|
select new WhileNode(condition, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, ProcedureCallNode> ProcedureCallParser()
|
||||||
|
{
|
||||||
|
return Choice(
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
from _ in Delimiter("(")
|
||||||
|
from expressions in ExpressionParser().SeparatedBy(Delimiter(","))
|
||||||
|
from _1 in Delimiter(")")
|
||||||
|
select new ProcedureCallNode(identifier, expressions),
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
select new ProcedureCallNode(identifier, [])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
||||||
{
|
{
|
||||||
return Choice<LexicalToken, SyntaxNodeBase>(
|
return Choice<LexicalToken, SyntaxNodeBase>(
|
||||||
|
@ -196,6 +217,7 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
from _ in Operator(":=")
|
from _ in Operator(":=")
|
||||||
from expression in ExpressionParser()
|
from expression in ExpressionParser()
|
||||||
select new AssignNode(variable, expression),
|
select new AssignNode(variable, expression),
|
||||||
|
ProcedureCallParser(),
|
||||||
IfParser(),
|
IfParser(),
|
||||||
ForParser(),
|
ForParser(),
|
||||||
WhileParser(),
|
WhileParser(),
|
||||||
|
@ -236,7 +258,7 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
select new ConstantNode(identifier, node);
|
select new ConstantNode(identifier, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, SyntaxNodeBase> ConstDeclarationsParser()
|
public static IParser<LexicalToken, BlockNode> ConstDeclarationsParser()
|
||||||
{
|
{
|
||||||
return (from _ in Keyword("const")
|
return (from _ in Keyword("const")
|
||||||
from tokens in ConstDeclarationParser().SeparatedOrEndBy1(Delimiter(";"))
|
from tokens in ConstDeclarationParser().SeparatedOrEndBy1(Delimiter(";"))
|
||||||
|
@ -283,12 +305,73 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
select new BlockNode(nodes)).Try(new BlockNode([]));
|
select new BlockNode(nodes)).Try(new BlockNode([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, ProgramBody> ProgramBodyParser()
|
public static IParser<LexicalToken, IEnumerable<Parameter>> ParameterParser()
|
||||||
|
{
|
||||||
|
return Choice(
|
||||||
|
from _ in Keyword("var")
|
||||||
|
from tokens in IdentifierParser().SeparatedBy1(Delimiter(","))
|
||||||
|
from _1 in Delimiter(":")
|
||||||
|
from typeToken in TypeParser()
|
||||||
|
select tokens.Select(x => new Parameter(true, x, typeToken)),
|
||||||
|
from tokens in IdentifierParser().SeparatedBy1(Delimiter(","))
|
||||||
|
from _ in Delimiter(":")
|
||||||
|
from typeToken in TypeParser()
|
||||||
|
select tokens.Select(x => new Parameter(false, x, typeToken))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, IEnumerable<Parameter>> FormalParameterParser()
|
||||||
|
{
|
||||||
|
return (from _ in Delimiter("(")
|
||||||
|
from parameters in ParameterParser().SeparatedBy(Delimiter(";"))
|
||||||
|
from _1 in Delimiter(")")
|
||||||
|
select parameters.Aggregate(new List<Parameter>(), (result, array) =>
|
||||||
|
{
|
||||||
|
result.AddRange(array);
|
||||||
|
return result;
|
||||||
|
})).Try([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, SubprogramHead> SubprogramHeadParser()
|
||||||
|
{
|
||||||
|
return Choice(
|
||||||
|
from _ in Keyword("procedure")
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
from parameters in FormalParameterParser()
|
||||||
|
select new SubprogramHead(identifier, parameters),
|
||||||
|
from _ in Keyword("function")
|
||||||
|
from identifier in IdentifierParser()
|
||||||
|
from parameters in FormalParameterParser()
|
||||||
|
from _1 in Delimiter(":")
|
||||||
|
from typeToken in TypeParser()
|
||||||
|
select new SubprogramHead(identifier, parameters, typeToken)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, SubprogramBody> SubprogramBodyParser()
|
||||||
{
|
{
|
||||||
return from constant in ConstDeclarationsParser()
|
return from constant in ConstDeclarationsParser()
|
||||||
from variables in VariableDeclarationsParser()
|
from variables in VariableDeclarationsParser()
|
||||||
from block in CompoundStatementParser()
|
from block in CompoundStatementParser()
|
||||||
select new ProgramBody(constant.Convert<BlockNode>(), variables, block);
|
select new SubprogramBody(constant, variables, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, Subprogram> SubprogramParser()
|
||||||
|
{
|
||||||
|
return from head in SubprogramHeadParser()
|
||||||
|
from _ in Delimiter(";")
|
||||||
|
from body in SubprogramBodyParser()
|
||||||
|
select new Subprogram(head, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IParser<LexicalToken, ProgramBody> ProgramBodyParser()
|
||||||
|
{
|
||||||
|
return from constant in ConstDeclarationsParser()
|
||||||
|
from variables in VariableDeclarationsParser()
|
||||||
|
from subprograms in SubprogramParser().SeparatedOrEndBy(Delimiter(";"))
|
||||||
|
.Map(x => new BlockNode(x))
|
||||||
|
from block in CompoundStatementParser()
|
||||||
|
select new ProgramBody(constant, variables, subprograms, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, ProgramHead> ProgramHeadParser()
|
public static IParser<LexicalToken, ProgramHead> ProgramHeadParser()
|
||||||
|
|
14
CanonSharp.Pascal/SyntaxTree/Parameter.cs
Normal file
14
CanonSharp.Pascal/SyntaxTree/Parameter.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using CanonSharp.Pascal.Scanner;
|
||||||
|
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class Parameter(bool isReference, LexicalToken identifier, SyntaxNodeBase typeNode) : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.Parameter;
|
||||||
|
|
||||||
|
public bool IsReference => isReference;
|
||||||
|
|
||||||
|
public LexicalToken Identifier => identifier;
|
||||||
|
|
||||||
|
public SyntaxNodeBase TypeNode => typeNode;
|
||||||
|
}
|
18
CanonSharp.Pascal/SyntaxTree/ProcedureCallNode.cs
Normal file
18
CanonSharp.Pascal/SyntaxTree/ProcedureCallNode.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using CanonSharp.Pascal.Scanner;
|
||||||
|
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class ProcedureCallNode : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public ProcedureCallNode(LexicalToken identifier, IEnumerable<SyntaxNodeBase> parameters)
|
||||||
|
{
|
||||||
|
Identifier = identifier;
|
||||||
|
Parameters.AddRange(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.ProcedureCall;
|
||||||
|
|
||||||
|
public LexicalToken Identifier { get; }
|
||||||
|
|
||||||
|
public List<SyntaxNodeBase> Parameters { get; } = [];
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
namespace CanonSharp.Pascal.SyntaxTree;
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
public sealed class ProgramBody(BlockNode constantDeclarations, BlockNode variableDeclarations, BlockNode mainBlock) : SyntaxNodeBase
|
public sealed class ProgramBody(BlockNode constantDeclarations, BlockNode variableDeclarations,
|
||||||
|
BlockNode subprograms,
|
||||||
|
BlockNode mainBlock)
|
||||||
|
: SyntaxNodeBase
|
||||||
{
|
{
|
||||||
public override SyntaxNodeType NodeType => SyntaxNodeType.ProgramBody;
|
public override SyntaxNodeType NodeType => SyntaxNodeType.ProgramBody;
|
||||||
|
|
||||||
|
@ -8,5 +11,7 @@ public sealed class ProgramBody(BlockNode constantDeclarations, BlockNode variab
|
||||||
|
|
||||||
public BlockNode VariableDeclarations => variableDeclarations;
|
public BlockNode VariableDeclarations => variableDeclarations;
|
||||||
|
|
||||||
|
public BlockNode Subprograms => subprograms;
|
||||||
|
|
||||||
public BlockNode MainBlock => mainBlock;
|
public BlockNode MainBlock => mainBlock;
|
||||||
}
|
}
|
||||||
|
|
10
CanonSharp.Pascal/SyntaxTree/Subprogram.cs
Normal file
10
CanonSharp.Pascal/SyntaxTree/Subprogram.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class Subprogram(SubprogramHead subprogramHead, SubprogramBody subprogramBody) : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.SubProgram;
|
||||||
|
|
||||||
|
public SubprogramHead Head => subprogramHead;
|
||||||
|
|
||||||
|
public SubprogramBody Body => subprogramBody;
|
||||||
|
}
|
12
CanonSharp.Pascal/SyntaxTree/SubprogramBody.cs
Normal file
12
CanonSharp.Pascal/SyntaxTree/SubprogramBody.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class SubprogramBody(BlockNode constDeclarations, BlockNode variableDeclarations, BlockNode mainBlock) : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.SubprogramBody;
|
||||||
|
|
||||||
|
public BlockNode ConstDeclarations => constDeclarations;
|
||||||
|
|
||||||
|
public BlockNode VariableDeclarations => variableDeclarations;
|
||||||
|
|
||||||
|
public BlockNode MainBlock => mainBlock;
|
||||||
|
}
|
28
CanonSharp.Pascal/SyntaxTree/SubprogramHead.cs
Normal file
28
CanonSharp.Pascal/SyntaxTree/SubprogramHead.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using CanonSharp.Pascal.Scanner;
|
||||||
|
|
||||||
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
|
public sealed class SubprogramHead : SyntaxNodeBase
|
||||||
|
{
|
||||||
|
public override SyntaxNodeType NodeType => SyntaxNodeType.SubprogramHead;
|
||||||
|
|
||||||
|
public LexicalToken Identifier { get; }
|
||||||
|
|
||||||
|
public List<Parameter> Parameters { get; } = [];
|
||||||
|
|
||||||
|
public SyntaxNodeBase? TypeToken { get; }
|
||||||
|
|
||||||
|
public SubprogramHead(LexicalToken identifier, IEnumerable<Parameter> parameters)
|
||||||
|
{
|
||||||
|
Identifier = identifier;
|
||||||
|
Parameters.AddRange(parameters);
|
||||||
|
TypeToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubprogramHead(LexicalToken identifier, IEnumerable<Parameter> parameters, SyntaxNodeBase typeToken) : this(
|
||||||
|
identifier, parameters)
|
||||||
|
{
|
||||||
|
TypeToken = typeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,11 @@ public enum SyntaxNodeType
|
||||||
If,
|
If,
|
||||||
While,
|
While,
|
||||||
For,
|
For,
|
||||||
|
ProcedureCall,
|
||||||
|
Parameter,
|
||||||
|
SubprogramHead,
|
||||||
|
SubprogramBody,
|
||||||
|
SubProgram,
|
||||||
ProgramBody,
|
ProgramBody,
|
||||||
ProgramHead,
|
ProgramHead,
|
||||||
Program
|
Program
|
||||||
|
|
|
@ -82,6 +82,23 @@ public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||||
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ProcedureCallTest()
|
||||||
|
{
|
||||||
|
ProcedureCallNode node = RunParser<ProcedureCallNode>(GrammarParser.FactorParser(), "test(1)");
|
||||||
|
Assert.Equal("test", node.Identifier.LiteralValue);
|
||||||
|
Assert.Single(node.Parameters);
|
||||||
|
Assert.Equal(1, node.Parameters[0].Convert<IntegerValueNode>().Value);
|
||||||
|
|
||||||
|
node = RunParser<ProcedureCallNode>(GrammarParser.FactorParser(), "test()");
|
||||||
|
Assert.Equal("test", node.Identifier.LiteralValue);
|
||||||
|
Assert.Empty(node.Parameters);
|
||||||
|
|
||||||
|
VariableNode variableNode = RunParser<VariableNode>(GrammarParser.FactorParser(), "test");
|
||||||
|
Assert.Equal("test", variableNode.Identifier.LiteralValue);
|
||||||
|
Assert.Empty(variableNode.Indexers);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SingleTermTest()
|
public void SingleTermTest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,6 +153,75 @@ public class ProgramParserTests : GrammarParserTestBase
|
||||||
i := i + 1;
|
i := i + 1;
|
||||||
end.
|
end.
|
||||||
""")]
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
procedure test;
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
function test(a, b : integer) : integer;
|
||||||
|
begin
|
||||||
|
test := 1;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
var i : integer;
|
||||||
|
begin
|
||||||
|
for i := 1 to 100 do
|
||||||
|
begin
|
||||||
|
doSomething(i);
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
begin
|
||||||
|
if 1 = 2 then
|
||||||
|
begin
|
||||||
|
test1;
|
||||||
|
test2 := a;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
doSomething;
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
var a : integer;
|
||||||
|
function test : integer;
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
test;
|
||||||
|
a := test;
|
||||||
|
test();
|
||||||
|
a := test();
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
procedure test();
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
test();
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
|
[InlineData("""
|
||||||
|
program main;
|
||||||
|
begin
|
||||||
|
test
|
||||||
|
end.
|
||||||
|
""")]
|
||||||
public void ProgramParseTest(string input)
|
public void ProgramParseTest(string input)
|
||||||
{
|
{
|
||||||
ProgramParse(input);
|
ProgramParse(input);
|
||||||
|
|
|
@ -83,6 +83,46 @@ public class StatementParserTests : GrammarParserTestBase
|
||||||
Assert.Equal("a", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("a", assignNode.Variable.Identifier.LiteralValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ProcedureCallTest1()
|
||||||
|
{
|
||||||
|
ProcedureCallNode node = RunParser<ProcedureCallNode>(GrammarParser.ProcedureCallParser(), "test()");
|
||||||
|
Assert.Equal("test", node.Identifier.LiteralValue);
|
||||||
|
Assert.Empty(node.Parameters);
|
||||||
|
|
||||||
|
node = RunParser<ProcedureCallNode>(GrammarParser.ProcedureCallParser(), "test");
|
||||||
|
Assert.Equal("test", node.Identifier.LiteralValue);
|
||||||
|
Assert.Empty(node.Parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ProcedureCallTest2()
|
||||||
|
{
|
||||||
|
ProcedureCallNode node = RunParser<ProcedureCallNode>(GrammarParser.ProcedureCallParser(),
|
||||||
|
"test(1 + 1, true)");
|
||||||
|
|
||||||
|
Assert.Equal(2, node.Parameters.Count);
|
||||||
|
|
||||||
|
BinaryOperatorNode firstParameter = node.Parameters[0].Convert<BinaryOperatorNode>();
|
||||||
|
Assert.Equal(BinaryOperatorType.Add, firstParameter.OperatorType);
|
||||||
|
|
||||||
|
BooleanValueNode secondParameter = node.Parameters[1].Convert<BooleanValueNode>();
|
||||||
|
Assert.True(secondParameter.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ProcedureCallTest3()
|
||||||
|
{
|
||||||
|
ProcedureCallNode node =
|
||||||
|
RunParser<ProcedureCallNode>(GrammarParser.ProcedureCallParser(), "test(1 * + 1, test2[0])");
|
||||||
|
|
||||||
|
Assert.Equal(2, node.Parameters.Count);
|
||||||
|
|
||||||
|
VariableNode secondParameter = node.Parameters[1].Convert<VariableNode>();
|
||||||
|
Assert.Equal("test2", secondParameter.Identifier.LiteralValue);
|
||||||
|
Assert.Single(secondParameter.Indexers);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("""
|
[InlineData("""
|
||||||
begin
|
begin
|
||||||
|
|
83
CanonSharp.Tests/ParserTests/SubprogramParserTests.cs
Normal file
83
CanonSharp.Tests/ParserTests/SubprogramParserTests.cs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
using CanonSharp.Pascal.Parser;
|
||||||
|
using CanonSharp.Pascal.SyntaxTree;
|
||||||
|
using CanonSharp.Tests.Utils;
|
||||||
|
|
||||||
|
namespace CanonSharp.Tests.ParserTests;
|
||||||
|
|
||||||
|
public class SubprogramParserTests : GrammarParserTestBase
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ParameterTest1()
|
||||||
|
{
|
||||||
|
List<Parameter> parameters = RunParser<Parameter>(GrammarParser.ParameterParser(), "a ,b : integer");
|
||||||
|
|
||||||
|
Assert.Equal(2, parameters.Count);
|
||||||
|
Assert.All(parameters, p =>
|
||||||
|
{
|
||||||
|
Assert.False(p.IsReference);
|
||||||
|
Assert.Equal("integer", p.TypeNode.Convert<TypeNode>().TypeToken.LiteralValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
parameters = RunParser<Parameter>(GrammarParser.ParameterParser(), "var a, b,c: real");
|
||||||
|
Assert.Equal(3, parameters.Count);
|
||||||
|
Assert.All(parameters, p =>
|
||||||
|
{
|
||||||
|
Assert.True(p.IsReference);
|
||||||
|
Assert.Equal("real", p.TypeNode.Convert<TypeNode>().TypeToken.LiteralValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("(var a, b : integer; c, d : real)", 4)]
|
||||||
|
[InlineData("(a : boolean; var c, d, e : char)", 4)]
|
||||||
|
[InlineData("(a : integer)", 1)]
|
||||||
|
[InlineData("(var b ,c : real)", 2)]
|
||||||
|
public void FormalParameterTest(string input, int count)
|
||||||
|
{
|
||||||
|
List<Parameter> parameters = RunParser<Parameter>(GrammarParser.FormalParameterParser(), input);
|
||||||
|
Assert.Equal(count, parameters.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("procedure test", 0)]
|
||||||
|
[InlineData("procedure test()", 0)]
|
||||||
|
[InlineData("procedure test(a : integer; var b : real)", 2)]
|
||||||
|
[InlineData("procedure test(a,b, c : real; var e, f : boolean)", 5)]
|
||||||
|
[InlineData("function test : integer", 0)]
|
||||||
|
[InlineData("function test() : real", 0)]
|
||||||
|
[InlineData("function test(a : integer; var b : real) : boolean", 2)]
|
||||||
|
[InlineData("function test(a,b, c : real; var e, f : boolean) : char", 5)]
|
||||||
|
public void SubprogramHeadTest(string input, int count)
|
||||||
|
{
|
||||||
|
SubprogramHead head = RunParser<SubprogramHead>(GrammarParser.SubprogramHeadParser(), input);
|
||||||
|
Assert.Equal(count, head.Parameters.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SubprogramHeadTest1()
|
||||||
|
{
|
||||||
|
SubprogramHead head =
|
||||||
|
RunParser<SubprogramHead>(GrammarParser.SubprogramHeadParser(), "function test(a : integer) : real");
|
||||||
|
|
||||||
|
Assert.Equal("test", head.Identifier.LiteralValue);
|
||||||
|
Assert.Single(head.Parameters);
|
||||||
|
Assert.NotNull(head.TypeToken);
|
||||||
|
Assert.Equal("real", head.TypeToken.Convert<TypeNode>().TypeToken.LiteralValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SubprogramBodyTest1()
|
||||||
|
{
|
||||||
|
SubprogramBody body = RunParser<SubprogramBody>(GrammarParser.SubprogramBodyParser(), """
|
||||||
|
const a = 3;
|
||||||
|
var c, d : integer; e, f :real;
|
||||||
|
begin
|
||||||
|
c := a + d;
|
||||||
|
end
|
||||||
|
""");
|
||||||
|
|
||||||
|
Assert.Single(body.ConstDeclarations.Statements);
|
||||||
|
Assert.Equal(2, body.VariableDeclarations.Statements.Count);
|
||||||
|
Assert.Equal(1, body.MainBlock.Statements.Count);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user