Compare commits
No commits in common. "97f9fb9ec3d079ebd36910575c117f548ac13281" and "eedbd5e7e56fd1fa0a9b1af076157e1212220cb7" have entirely different histories.
97f9fb9ec3
...
eedbd5e7e5
|
@ -139,15 +139,8 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
|
|
||||||
public static IParser<LexicalToken, VariableNode> VariableParser()
|
public static IParser<LexicalToken, VariableNode> VariableParser()
|
||||||
{
|
{
|
||||||
return Choice(
|
return from token in Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Identifier)
|
||||||
from token in IdentifierParser()
|
select new VariableNode(token.LiteralValue);
|
||||||
from _ in Delimiter("[")
|
|
||||||
from expressions in ExpressionsParser()
|
|
||||||
from _1 in Delimiter("]")
|
|
||||||
select new VariableNode(token, expressions),
|
|
||||||
from token in IdentifierParser()
|
|
||||||
select new VariableNode(token)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
||||||
|
@ -200,28 +193,10 @@ public sealed class GrammarParser : GrammarParserBuilder
|
||||||
select new BlockNode(tokens)).Try(new BlockNode([]));
|
select new BlockNode(tokens)).Try(new BlockNode([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, TypeNode> ArrayTypeParser()
|
|
||||||
{
|
|
||||||
IParser<LexicalToken, IEnumerable<ArrayRange>> arrayRangeParser = (
|
|
||||||
from left in IntegerParser()
|
|
||||||
from _ in Delimiter("..")
|
|
||||||
from right in IntegerParser()
|
|
||||||
select new ArrayRange(left.Value, right.Value)).SeparatedBy1(Delimiter(","));
|
|
||||||
|
|
||||||
return from _ in Keyword("array")
|
|
||||||
from _1 in Delimiter("[")
|
|
||||||
from ranges in arrayRangeParser
|
|
||||||
from _2 in Delimiter("]")
|
|
||||||
from _3 in Keyword("of")
|
|
||||||
from typeToken in BasicTypeParser()
|
|
||||||
select new TypeNode(typeToken, ranges);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IParser<LexicalToken, SyntaxNodeBase> TypeParser()
|
public static IParser<LexicalToken, SyntaxNodeBase> TypeParser()
|
||||||
{
|
{
|
||||||
return Choice(ArrayTypeParser(),
|
return from token in BasicTypeParser()
|
||||||
from token in BasicTypeParser()
|
select new TypeNode(token);
|
||||||
select new TypeNode(token));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<LexicalToken, VariableDeclarationNode> VariableDeclarationParser()
|
public static IParser<LexicalToken, VariableDeclarationNode> VariableDeclarationParser()
|
||||||
|
|
|
@ -9,9 +9,7 @@ namespace CanonSharp.Pascal.Parser;
|
||||||
public abstract class GrammarParserBuilder
|
public abstract class GrammarParserBuilder
|
||||||
{
|
{
|
||||||
protected static IParser<LexicalToken, LexicalToken> Keyword(string value)
|
protected static IParser<LexicalToken, LexicalToken> Keyword(string value)
|
||||||
=> Satisfy<LexicalToken>(token =>
|
=> Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Keyword && token.LiteralValue == value);
|
||||||
token.TokenType == LexicalTokenType.Keyword &&
|
|
||||||
token.LiteralValue.Equals(value, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
protected static IParser<LexicalToken, LexicalToken> Operator(string value)
|
protected static IParser<LexicalToken, LexicalToken> Operator(string value)
|
||||||
=> Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Operator && token.LiteralValue == value);
|
=> Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Operator && token.LiteralValue == value);
|
||||||
|
@ -31,12 +29,6 @@ public abstract class GrammarParserBuilder
|
||||||
select new BooleanValueNode(false);
|
select new BooleanValueNode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static IParser<LexicalToken, IntegerValueNode> IntegerParser()
|
|
||||||
{
|
|
||||||
return from token in Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.ConstInteger)
|
|
||||||
select new IntegerValueNode(int.Parse(token.LiteralValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static IParser<LexicalToken, SyntaxNodeBase> NumberParser()
|
protected static IParser<LexicalToken, SyntaxNodeBase> NumberParser()
|
||||||
{
|
{
|
||||||
return Choice<LexicalToken, SyntaxNodeBase>(
|
return Choice<LexicalToken, SyntaxNodeBase>(
|
||||||
|
@ -62,9 +54,4 @@ public abstract class GrammarParserBuilder
|
||||||
Keyword("char")
|
Keyword("char")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static IParser<LexicalToken, LexicalToken> IdentifierParser()
|
|
||||||
{
|
|
||||||
return Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Identifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,14 +98,9 @@ public sealed class LexicalScanner
|
||||||
|
|
||||||
public static IParser<char, LexicalToken> ConstIntegerParser()
|
public static IParser<char, LexicalToken> ConstIntegerParser()
|
||||||
{
|
{
|
||||||
return Choice(
|
return from nums in AsciiDigit().Many1()
|
||||||
from nums in AsciiDigit().Many1()
|
|
||||||
from _ in String("..").LookAhead()
|
|
||||||
select new LexicalToken(LexicalTokenType.ConstInteger, new string(nums.ToArray())),
|
|
||||||
from nums in AsciiDigit().Many1()
|
|
||||||
from _ in Char('.').LookAhead().Not()
|
from _ in Char('.').LookAhead().Not()
|
||||||
select new LexicalToken(LexicalTokenType.ConstInteger, new string(nums.ToArray()))
|
select new LexicalToken(LexicalTokenType.ConstInteger, new string(nums.ToArray()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IParser<char, LexicalToken> ConstFloatParser()
|
public static IParser<char, LexicalToken> ConstFloatParser()
|
||||||
|
@ -147,8 +142,8 @@ public sealed class LexicalScanner
|
||||||
return JunkParser().SkipTill(Choice(KeywordParser(),
|
return JunkParser().SkipTill(Choice(KeywordParser(),
|
||||||
DelimiterParser(),
|
DelimiterParser(),
|
||||||
OperatorParser(),
|
OperatorParser(),
|
||||||
ConstFloatParser(),
|
|
||||||
ConstIntegerParser(),
|
ConstIntegerParser(),
|
||||||
|
ConstFloatParser(),
|
||||||
CharParser(),
|
CharParser(),
|
||||||
IdentifierParser())).Many();
|
IdentifierParser())).Many();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,9 @@
|
||||||
|
|
||||||
namespace CanonSharp.Pascal.SyntaxTree;
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
public record struct ArrayRange(int Left, int Right);
|
public sealed class TypeNode(LexicalToken typeToken) : SyntaxNodeBase
|
||||||
|
|
||||||
public sealed class TypeNode : SyntaxNodeBase
|
|
||||||
{
|
{
|
||||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Type;
|
public override SyntaxNodeType NodeType => SyntaxNodeType.Type;
|
||||||
|
|
||||||
public LexicalToken TypeToken { get; }
|
public LexicalToken TypeToken => typeToken;
|
||||||
|
|
||||||
public List<ArrayRange> ArrayRanges { get; } = [];
|
|
||||||
|
|
||||||
public TypeNode(LexicalToken typeToken)
|
|
||||||
{
|
|
||||||
TypeToken = typeToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeNode(LexicalToken typeToken, IEnumerable<ArrayRange> arrayRanges) : this(typeToken)
|
|
||||||
{
|
|
||||||
ArrayRanges.AddRange(arrayRanges);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,8 @@
|
||||||
using CanonSharp.Pascal.Scanner;
|
namespace CanonSharp.Pascal.SyntaxTree;
|
||||||
|
|
||||||
namespace CanonSharp.Pascal.SyntaxTree;
|
public sealed class VariableNode(string name) : SyntaxNodeBase
|
||||||
|
|
||||||
public sealed class VariableNode : SyntaxNodeBase
|
|
||||||
{
|
{
|
||||||
public override SyntaxNodeType NodeType => SyntaxNodeType.Variable;
|
public override SyntaxNodeType NodeType => SyntaxNodeType.Variable;
|
||||||
|
|
||||||
public LexicalToken Identifier { get; }
|
public string IdentifierName => name;
|
||||||
|
|
||||||
public List<SyntaxNodeBase> Indexers { get; } = [];
|
|
||||||
|
|
||||||
public VariableNode(LexicalToken identifier)
|
|
||||||
{
|
|
||||||
Identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VariableNode(LexicalToken identifier, IEnumerable<SyntaxNodeBase> expressions)
|
|
||||||
{
|
|
||||||
Identifier = identifier;
|
|
||||||
Indexers.AddRange(expressions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,52 +41,15 @@ public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||||
[Fact]
|
[Fact]
|
||||||
public void IdentifierTest()
|
public void IdentifierTest()
|
||||||
{
|
{
|
||||||
VariableNode node = RunParser<VariableNode>(GrammarParser.VariableParser(), "temp");
|
VariableNode node = RunParser<VariableNode>(GrammarParser.FactorParser(), "temp");
|
||||||
Assert.Equal("temp", node.Identifier.LiteralValue);
|
Assert.Equal("temp", node.IdentifierName);
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ArrayIdentifierTest()
|
|
||||||
{
|
|
||||||
VariableNode node = RunParser<VariableNode>(GrammarParser.VariableParser(), "a[0]");
|
|
||||||
Assert.Equal("a", node.Identifier.LiteralValue);
|
|
||||||
Assert.Single(node.Indexers);
|
|
||||||
Assert.Equal(0, node.Indexers.First().Convert<IntegerValueNode>().Value);
|
|
||||||
|
|
||||||
node = RunParser<VariableNode>(GrammarParser.VariableParser(), "a[i + 1]");
|
|
||||||
Assert.Equal("a", node.Identifier.LiteralValue);
|
|
||||||
Assert.Single(node.Indexers);
|
|
||||||
BinaryOperatorNode binaryOperatorNode = node.Indexers.First().Convert<BinaryOperatorNode>();
|
|
||||||
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
|
||||||
Assert.Equal("i", binaryOperatorNode.Left.Convert<VariableNode>().Identifier.LiteralValue);
|
|
||||||
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
|
||||||
|
|
||||||
node = RunParser<VariableNode>(GrammarParser.VariableParser(), "a[b[i + 1] - 10, c]");
|
|
||||||
Assert.Equal("a", node.Identifier.LiteralValue);
|
|
||||||
Assert.Equal(2, node.Indexers.Count);
|
|
||||||
|
|
||||||
VariableNode secondNode = node.Indexers[1].Convert<VariableNode>();
|
|
||||||
Assert.Equal("c", secondNode.Identifier.LiteralValue);
|
|
||||||
Assert.Empty(secondNode.Indexers);
|
|
||||||
|
|
||||||
BinaryOperatorNode firstNode = node.Indexers[0].Convert<BinaryOperatorNode>();
|
|
||||||
Assert.Equal(BinaryOperatorType.Subtract, firstNode.OperatorType);
|
|
||||||
Assert.Equal(10, firstNode.Right.Convert<IntegerValueNode>().Value);
|
|
||||||
|
|
||||||
VariableNode variableNode = firstNode.Left.Convert<VariableNode>();
|
|
||||||
Assert.Equal("b", variableNode.Identifier.LiteralValue);
|
|
||||||
Assert.Single(variableNode.Indexers);
|
|
||||||
binaryOperatorNode = variableNode.Indexers[0].Convert<BinaryOperatorNode>();
|
|
||||||
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
|
||||||
Assert.Equal("i", binaryOperatorNode.Left.Convert<VariableNode>().Identifier.LiteralValue);
|
|
||||||
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SingleTermTest()
|
public void SingleTermTest()
|
||||||
{
|
{
|
||||||
VariableNode node = RunParser<VariableNode>(GrammarParser.TermParser(), "temp");
|
VariableNode node = RunParser<VariableNode>(GrammarParser.TermParser(), "temp");
|
||||||
Assert.Equal("temp", node.Identifier.LiteralValue);
|
Assert.Equal("temp", node.IdentifierName);
|
||||||
|
|
||||||
UnaryOperatorNode unaryOperatorNode = RunParser<UnaryOperatorNode>(GrammarParser.TermParser(), "- 123");
|
UnaryOperatorNode unaryOperatorNode = RunParser<UnaryOperatorNode>(GrammarParser.TermParser(), "- 123");
|
||||||
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
Assert.Equal(UnaryOperatorType.Minus, unaryOperatorNode.OperatorType);
|
||||||
|
@ -126,7 +89,7 @@ public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||||
Assert.Equal(3, node.Right.Convert<IntegerValueNode>().Value);
|
Assert.Equal(3, node.Right.Convert<IntegerValueNode>().Value);
|
||||||
BinaryOperatorNode leftNode = node.Left.Convert<BinaryOperatorNode>();
|
BinaryOperatorNode leftNode = node.Left.Convert<BinaryOperatorNode>();
|
||||||
Assert.Equal(BinaryOperatorType.Multiply, leftNode.OperatorType);
|
Assert.Equal(BinaryOperatorType.Multiply, leftNode.OperatorType);
|
||||||
Assert.Equal("temp", leftNode.Left.Convert<VariableNode>().Identifier.LiteralValue);
|
Assert.Equal("temp", leftNode.Left.Convert<VariableNode>().IdentifierName);
|
||||||
Assert.Equal(2, leftNode.Right.Convert<IntegerValueNode>().Value);
|
Assert.Equal(2, leftNode.Right.Convert<IntegerValueNode>().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +97,7 @@ public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||||
public void SimpleExpressionTest1()
|
public void SimpleExpressionTest1()
|
||||||
{
|
{
|
||||||
VariableNode node = RunParser<VariableNode>(GrammarParser.SimpleExpressionParser(), "temp");
|
VariableNode node = RunParser<VariableNode>(GrammarParser.SimpleExpressionParser(), "temp");
|
||||||
Assert.Equal("temp", node.Identifier.LiteralValue);
|
Assert.Equal("temp", node.IdentifierName);
|
||||||
|
|
||||||
UnaryOperatorNode unaryOperatorNode =
|
UnaryOperatorNode unaryOperatorNode =
|
||||||
RunParser<UnaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "- 123");
|
RunParser<UnaryOperatorNode>(GrammarParser.SimpleExpressionParser(), "- 123");
|
||||||
|
@ -275,6 +238,8 @@ public sealed class ExpressionParserTests : GrammarParserTestBase
|
||||||
public void VariableTest1()
|
public void VariableTest1()
|
||||||
{
|
{
|
||||||
VariableNode node = RunParser<VariableNode>(GrammarParser.VariableParser(), "temp");
|
VariableNode node = RunParser<VariableNode>(GrammarParser.VariableParser(), "temp");
|
||||||
Assert.Equal("temp", node.Identifier.LiteralValue);
|
Assert.Equal("temp", node.IdentifierName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ProgramParserTests : GrammarParserTestBase
|
||||||
Assert.Equal("main", program.Head.ProgramName.LiteralValue);
|
Assert.Equal("main", program.Head.ProgramName.LiteralValue);
|
||||||
|
|
||||||
AssignNode assignNode = program.Body.MainBlock.Statements[0].Convert<AssignNode>();
|
AssignNode assignNode = program.Body.MainBlock.Statements[0].Convert<AssignNode>();
|
||||||
Assert.Equal("temp", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||||
|
|
||||||
BinaryOperatorNode binaryOperatorNode = assignNode.Expression.Convert<BinaryOperatorNode>();
|
BinaryOperatorNode binaryOperatorNode = assignNode.Expression.Convert<BinaryOperatorNode>();
|
||||||
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
||||||
|
@ -59,87 +59,11 @@ public class ProgramParserTests : GrammarParserTestBase
|
||||||
Assert.Equal("b", constantNodes[1].Identifier.LiteralValue);
|
Assert.Equal("b", constantNodes[1].Identifier.LiteralValue);
|
||||||
|
|
||||||
AssignNode assignNode = program.Body.MainBlock.Statements[0].Convert<AssignNode>();
|
AssignNode assignNode = program.Body.MainBlock.Statements[0].Convert<AssignNode>();
|
||||||
Assert.Equal("temp", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||||
|
|
||||||
BinaryOperatorNode binaryOperatorNode = assignNode.Expression.Convert<BinaryOperatorNode>();
|
BinaryOperatorNode binaryOperatorNode = assignNode.Expression.Convert<BinaryOperatorNode>();
|
||||||
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
Assert.Equal(BinaryOperatorType.Add, binaryOperatorNode.OperatorType);
|
||||||
Assert.Equal(1, binaryOperatorNode.Left.Convert<IntegerValueNode>().Value);
|
Assert.Equal(1, binaryOperatorNode.Left.Convert<IntegerValueNode>().Value);
|
||||||
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
Assert.Equal(1, binaryOperatorNode.Right.Convert<IntegerValueNode>().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ProgramParseTest4()
|
|
||||||
{
|
|
||||||
Program program = ProgramParse("""
|
|
||||||
program main;
|
|
||||||
var a : integer;
|
|
||||||
begin
|
|
||||||
a := 1 + 1;
|
|
||||||
end.
|
|
||||||
""");
|
|
||||||
|
|
||||||
IList<VariableDeclarationNode> variableDeclarationNodes = program.Body.VariableDeclarations.Statements
|
|
||||||
.Select(x => x.Convert<VariableDeclarationNode>()).ToList();
|
|
||||||
Assert.Single(variableDeclarationNodes);
|
|
||||||
Assert.Single(variableDeclarationNodes.First().Identifiers);
|
|
||||||
Assert.Equal("a", variableDeclarationNodes.First().Identifiers.First().LiteralValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("""
|
|
||||||
program DoNothing;
|
|
||||||
begin
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program Add;
|
|
||||||
var a : Integer;
|
|
||||||
begin
|
|
||||||
a := 1 + 1
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program varTest;
|
|
||||||
var a : integer;
|
|
||||||
begin
|
|
||||||
a := 9 div 1;
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program main;
|
|
||||||
var a : integer;
|
|
||||||
begin
|
|
||||||
a := 1 + +1;
|
|
||||||
a := 1 - -1;
|
|
||||||
a := 1 + -1;
|
|
||||||
a := 1 - +1;
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program main;
|
|
||||||
const a = true; b = false;
|
|
||||||
var c, d : boolean;
|
|
||||||
begin
|
|
||||||
c := true;
|
|
||||||
d := false;
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program arrayTest;
|
|
||||||
var a : array [0..10] of integer;
|
|
||||||
begin
|
|
||||||
a[0] := 1;
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
[InlineData("""
|
|
||||||
program arrayTest;
|
|
||||||
var a : array [10..100, 0..10] of integer;
|
|
||||||
begin
|
|
||||||
a[10,0] := 1;
|
|
||||||
end.
|
|
||||||
""")]
|
|
||||||
public void ProgramParseTest(string input)
|
|
||||||
{
|
|
||||||
ProgramParse(input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class StatementParserTests : GrammarParserTestBase
|
||||||
{
|
{
|
||||||
AssignNode node = RunParser<AssignNode>(GrammarParser.StatementParser(), "temp := 1");
|
AssignNode node = RunParser<AssignNode>(GrammarParser.StatementParser(), "temp := 1");
|
||||||
|
|
||||||
Assert.Equal("temp", node.Variable.Identifier.LiteralValue);
|
Assert.Equal("temp", node.Variable.IdentifierName);
|
||||||
Assert.Equal(1, node.Expression.Convert<IntegerValueNode>().Value);
|
Assert.Equal(1, node.Expression.Convert<IntegerValueNode>().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ public class StatementParserTests : GrammarParserTestBase
|
||||||
|
|
||||||
Assert.Equal(2, node.Statements.Count);
|
Assert.Equal(2, node.Statements.Count);
|
||||||
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
||||||
Assert.Equal("temp", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||||
|
|
||||||
assignNode = node.Statements[1].Convert<AssignNode>();
|
assignNode = node.Statements[1].Convert<AssignNode>();
|
||||||
Assert.Equal("flag", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("flag", assignNode.Variable.IdentifierName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -74,9 +74,9 @@ public class StatementParserTests : GrammarParserTestBase
|
||||||
|
|
||||||
Assert.Equal(2, node.Statements.Count);
|
Assert.Equal(2, node.Statements.Count);
|
||||||
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
AssignNode assignNode = node.Statements[0].Convert<AssignNode>();
|
||||||
Assert.Equal("temp", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("temp", assignNode.Variable.IdentifierName);
|
||||||
|
|
||||||
assignNode = node.Statements[1].Convert<AssignNode>();
|
assignNode = node.Statements[1].Convert<AssignNode>();
|
||||||
Assert.Equal("flag", assignNode.Variable.Identifier.LiteralValue);
|
Assert.Equal("flag", assignNode.Variable.IdentifierName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,72 +11,10 @@ public class VariableDeclarationTests : GrammarParserTestBase
|
||||||
[InlineData("integer", "integer")]
|
[InlineData("integer", "integer")]
|
||||||
[InlineData("char", "char")]
|
[InlineData("char", "char")]
|
||||||
[InlineData("real", "real")]
|
[InlineData("real", "real")]
|
||||||
public void BasicTypeParseTest(string input, string value)
|
public void TypeParseTest(string input, string value)
|
||||||
{
|
{
|
||||||
TypeNode node = RunParser<TypeNode>(GrammarParser.TypeParser(), input);
|
TypeNode node = RunParser<TypeNode>(GrammarParser.TypeParser(), input);
|
||||||
Assert.Equal(value, node.TypeToken.LiteralValue);
|
Assert.Equal(value, node.TypeToken.LiteralValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ArrayTypeParseTest()
|
|
||||||
{
|
|
||||||
TypeNode node = RunParser<TypeNode>(GrammarParser.ArrayTypeParser(), "array [0..9] of integer");
|
|
||||||
|
|
||||||
Assert.Equal("integer", node.TypeToken.LiteralValue);
|
|
||||||
Assert.Single(node.ArrayRanges);
|
|
||||||
Assert.Equal(new ArrayRange(0, 9), node.ArrayRanges.First());
|
|
||||||
|
|
||||||
node = RunParser<TypeNode>(GrammarParser.ArrayTypeParser(), "array [0..10,0..10] of char");
|
|
||||||
Assert.Equal("char", node.TypeToken.LiteralValue);
|
|
||||||
Assert.Equal(2, node.ArrayRanges.Count);
|
|
||||||
Assert.Equal(new ArrayRange(0, 10), node.ArrayRanges[0]);
|
|
||||||
Assert.Equal(new ArrayRange(0, 10), node.ArrayRanges[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void VariableDeclarationTest()
|
|
||||||
{
|
|
||||||
VariableDeclarationNode node = RunParser<VariableDeclarationNode>(GrammarParser.VariableDeclarationParser(),
|
|
||||||
"a : integer");
|
|
||||||
|
|
||||||
Assert.Contains(node.Identifiers, token => token.LiteralValue == "a");
|
|
||||||
Assert.Equal("integer", node.TypeNode.TypeToken.LiteralValue);
|
|
||||||
|
|
||||||
node = RunParser<VariableDeclarationNode>(GrammarParser.VariableDeclarationParser(),
|
|
||||||
"a, b, c : boolean");
|
|
||||||
|
|
||||||
Assert.Contains(node.Identifiers, token => token.LiteralValue == "a");
|
|
||||||
Assert.Contains(node.Identifiers, token => token.LiteralValue == "b");
|
|
||||||
Assert.Contains(node.Identifiers, token => token.LiteralValue == "c");
|
|
||||||
Assert.Equal("boolean", node.TypeNode.TypeToken.LiteralValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ArrayVariableDeclarationTest()
|
|
||||||
{
|
|
||||||
VariableDeclarationNode node = RunParser<VariableDeclarationNode>(GrammarParser.VariableDeclarationParser(),
|
|
||||||
"test_array: array [0..9,10..20] of real");
|
|
||||||
|
|
||||||
Assert.Single(node.Identifiers);
|
|
||||||
Assert.Contains(node.Identifiers, token => token.LiteralValue == "test_array");
|
|
||||||
Assert.Equal("real", node.TypeNode.TypeToken.LiteralValue);
|
|
||||||
|
|
||||||
Assert.Equal(2, node.TypeNode.ArrayRanges.Count);
|
|
||||||
Assert.Equal(new ArrayRange(0, 9), node.TypeNode.ArrayRanges[0]);
|
|
||||||
Assert.Equal(new ArrayRange(10, 20), node.TypeNode.ArrayRanges[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("var a : integer;", 1)]
|
|
||||||
[InlineData("var a : integer; b : boolean;", 2)]
|
|
||||||
[InlineData("var a : integer; b,c : boolean;" +
|
|
||||||
"d : char", 3)]
|
|
||||||
[InlineData("var a,d,e : integer; b : boolean; c: real;", 3)]
|
|
||||||
[InlineData("var a : array [0..5] of integer", 1)]
|
|
||||||
[InlineData("var a,b,c: array [0..9,10..20] of integer; c,d : boolean", 2)]
|
|
||||||
public void VariableDeclarationsTest(string input, int count)
|
|
||||||
{
|
|
||||||
BlockNode node = RunParser<BlockNode>(GrammarParser.VariableDeclarationsParser(), input);
|
|
||||||
Assert.Equal(count, node.Statements.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -131,21 +131,6 @@ public class LexicalParserTests : LexicalTestBase
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void LexicalParserTest4()
|
|
||||||
{
|
|
||||||
ValidateLexicalTokens(LexicalScanner.PascalParser(), "array [0..9] of integer", [
|
|
||||||
(LexicalTokenType.Keyword, "array"),
|
|
||||||
(LexicalTokenType.Delimiter, "["),
|
|
||||||
(LexicalTokenType.ConstInteger, "0"),
|
|
||||||
(LexicalTokenType.Delimiter, ".."),
|
|
||||||
(LexicalTokenType.ConstInteger, "9"),
|
|
||||||
(LexicalTokenType.Delimiter, "]"),
|
|
||||||
(LexicalTokenType.Keyword, "of"),
|
|
||||||
(LexicalTokenType.Keyword, "integer")
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("""
|
[InlineData("""
|
||||||
program exFunction;
|
program exFunction;
|
||||||
|
|
|
@ -107,7 +107,6 @@ public class LexicalTokenParserTest : LexicalTestBase
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(123, "123")]
|
[InlineData(123, "123")]
|
||||||
[InlineData(0, "0")]
|
[InlineData(0, "0")]
|
||||||
[InlineData(10, "10..20")]
|
|
||||||
public void ConstIntegerTest(int value, string input)
|
public void ConstIntegerTest(int value, string input)
|
||||||
{
|
{
|
||||||
StringReadState state = new(input);
|
StringReadState state = new(input);
|
||||||
|
|
|
@ -24,15 +24,13 @@ public abstract class LexicalTestBase
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void ValidateLexicalTokens(IParser<char, IEnumerable<LexicalToken>> parser, string input,
|
protected static void ValidateLexicalTokens(IParser<char, IEnumerable<LexicalToken>> parser, string input,
|
||||||
List<(LexicalTokenType, string)> exceptedResult)
|
IEnumerable<(LexicalTokenType, string)> exceptedResult)
|
||||||
{
|
{
|
||||||
StringReadState state = new(input);
|
StringReadState state = new(input);
|
||||||
IParseResult<char, IEnumerable<LexicalToken>> result = parser.Parse(state);
|
IParseResult<char, IEnumerable<LexicalToken>> result = parser.Parse(state);
|
||||||
List<LexicalToken> actualResult = result.Value.ToList();
|
|
||||||
|
|
||||||
Assert.Equal(exceptedResult.Count, actualResult.Count);
|
|
||||||
foreach (((LexicalTokenType exceptedType, string exceptedValue), LexicalToken token) in exceptedResult.Zip(
|
foreach (((LexicalTokenType exceptedType, string exceptedValue), LexicalToken token) in exceptedResult.Zip(
|
||||||
actualResult))
|
result.Value))
|
||||||
{
|
{
|
||||||
Assert.Equal(exceptedType, token.TokenType);
|
Assert.Equal(exceptedType, token.TokenType);
|
||||||
Assert.Equal(exceptedValue, token.LiteralValue);
|
Assert.Equal(exceptedValue, token.LiteralValue);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user