242 lines
8.7 KiB
C#
242 lines
8.7 KiB
C#
using CanonSharp.Combinator.Abstractions;
|
|
using CanonSharp.Combinator.Extensions;
|
|
using static CanonSharp.Combinator.ParserBuilder;
|
|
using CanonSharp.Pascal.Scanner;
|
|
using CanonSharp.Pascal.SyntaxTree;
|
|
|
|
namespace CanonSharp.Pascal.Parser;
|
|
|
|
public sealed class GrammarParser : GrammarParserBuilder
|
|
{
|
|
public static IParser<LexicalToken, SyntaxNodeBase> FactorParser()
|
|
{
|
|
// factor -> - factor | + factor
|
|
IParser<LexicalToken, SyntaxNodeBase> minusParser =
|
|
from _ in Operator("-")
|
|
from node in FactorParser()
|
|
select new UnaryOperatorNode(UnaryOperatorType.Minus, node);
|
|
|
|
IParser<LexicalToken, SyntaxNodeBase> plusParser =
|
|
from _ in Operator("+")
|
|
from node in FactorParser()
|
|
select new UnaryOperatorNode(UnaryOperatorType.Plus, node);
|
|
|
|
IParser<LexicalToken, SyntaxNodeBase> notParser =
|
|
from _ in Keyword("not")
|
|
from node in FactorParser()
|
|
select new UnaryOperatorNode(UnaryOperatorType.Not, node);
|
|
|
|
IParser<LexicalToken, SyntaxNodeBase> parenthesisParser =
|
|
from _1 in Delimiter("(")
|
|
from node in ExpressionParser()
|
|
from _2 in Delimiter(")")
|
|
select node;
|
|
|
|
return Choice(
|
|
TrueParser(),
|
|
FalseParser(),
|
|
NumberParser(),
|
|
minusParser,
|
|
plusParser,
|
|
notParser,
|
|
VariableParser(),
|
|
parenthesisParser
|
|
);
|
|
}
|
|
|
|
private static IParser<LexicalToken, SyntaxNodeBase> TermRecursively(SyntaxNodeBase left)
|
|
{
|
|
// MultiplyOperator -> * | / | div | mod | and
|
|
IParser<LexicalToken, BinaryOperatorType> multiplyOperator = Choice(
|
|
from _ in Operator("*")
|
|
select BinaryOperatorType.Multiply,
|
|
from _ in Operator("/")
|
|
select BinaryOperatorType.Divide,
|
|
from _ in Keyword("div")
|
|
select BinaryOperatorType.IntegerDivide,
|
|
from _ in Keyword("mod")
|
|
select BinaryOperatorType.Mod,
|
|
from _ in Keyword("and")
|
|
select BinaryOperatorType.And);
|
|
|
|
return multiplyOperator.Next(op =>
|
|
{
|
|
return FactorParser().Map(right => new BinaryOperatorNode(op, left, right))
|
|
.Bind(TermRecursively);
|
|
}, left);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> TermParser()
|
|
{
|
|
// Term -> Factor | Term MultiplyOperator Factor
|
|
// 消除左递归为
|
|
// Term -> Factor Term'
|
|
// Term' -> MultiplyOperator Factor Term' | ε
|
|
return FactorParser().Bind(TermRecursively);
|
|
}
|
|
|
|
private static IParser<LexicalToken, SyntaxNodeBase> SimpleExpressionRecursively(SyntaxNodeBase left)
|
|
{
|
|
// AddOperator -> + | - | or
|
|
IParser<LexicalToken, BinaryOperatorType> addOperator = Choice(
|
|
from _ in Operator("+")
|
|
select BinaryOperatorType.Add,
|
|
from _ in Operator("-")
|
|
select BinaryOperatorType.Subtract,
|
|
from _ in Keyword("or")
|
|
select BinaryOperatorType.Or);
|
|
|
|
return addOperator.Next(op =>
|
|
{
|
|
return TermParser().Map(right => new BinaryOperatorNode(op, left, right))
|
|
.Bind(SimpleExpressionRecursively);
|
|
}, left);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> SimpleExpressionParser()
|
|
{
|
|
// SimpleExpression -> Term | SimpleExpression AddOperator Term
|
|
// 消除左递归为
|
|
// SimpleExpression -> Term SimpleExpression'
|
|
// SimpleExpression' -> AddOperator Term SimpleExpression' | ε
|
|
return TermParser().Bind(SimpleExpressionRecursively);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> ExpressionParser()
|
|
{
|
|
// RelationOperator -> = | <> | < | <= | > | >=
|
|
IParser<LexicalToken, BinaryOperatorType> relationOperator = Choice(
|
|
from _ in Operator("=")
|
|
select BinaryOperatorType.Equal,
|
|
from _ in Operator("<>")
|
|
select BinaryOperatorType.NotEqual,
|
|
from _ in Operator("<")
|
|
select BinaryOperatorType.Less,
|
|
from _ in Operator("<=")
|
|
select BinaryOperatorType.LessEqual,
|
|
from _ in Operator(">")
|
|
select BinaryOperatorType.Greater,
|
|
from _ in Operator(">=")
|
|
select BinaryOperatorType.GreaterEqual);
|
|
|
|
// Expression -> SimpleExpression | SimpleExpression RelationOperator SimpleExpression
|
|
return Choice(
|
|
from left in SimpleExpressionParser()
|
|
from op in relationOperator
|
|
from right in SimpleExpressionParser()
|
|
select new BinaryOperatorNode(op, left, right),
|
|
SimpleExpressionParser()
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// ExpressionList Parser
|
|
/// ExpressionList -> Expression | ExpressionList , Expression
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static IParser<LexicalToken, IEnumerable<SyntaxNodeBase>> ExpressionsParser()
|
|
=> ExpressionParser().SeparatedBy1(Delimiter(","));
|
|
|
|
public static IParser<LexicalToken, VariableNode> VariableParser()
|
|
{
|
|
return from token in Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Identifier)
|
|
select new VariableNode(token.LiteralValue);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> StatementParser()
|
|
{
|
|
return Choice(
|
|
from variable in VariableParser()
|
|
from _ in Operator(":=")
|
|
from expression in ExpressionParser()
|
|
select new AssignNode(variable, expression)
|
|
);
|
|
}
|
|
|
|
public static IParser<LexicalToken, BlockNode> CompoundStatementParser()
|
|
{
|
|
return from _1 in Keyword("begin")
|
|
from statements in StatementParser().SeparatedOrEndBy(Delimiter(";"))
|
|
from _2 in Keyword("end")
|
|
select new BlockNode(statements);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> ConstValueParser()
|
|
{
|
|
return Choice(
|
|
from _ in Operator("-")
|
|
from num in NumberParser()
|
|
select new UnaryOperatorNode(UnaryOperatorType.Minus, num),
|
|
from _ in Operator("+")
|
|
from num in NumberParser()
|
|
select new UnaryOperatorNode(UnaryOperatorType.Plus, num),
|
|
NumberParser(),
|
|
CharParser(),
|
|
TrueParser(),
|
|
FalseParser()
|
|
);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> ConstDeclarationParser()
|
|
{
|
|
return from identifier in Satisfy<LexicalToken>(token =>
|
|
token.TokenType == LexicalTokenType.Identifier)
|
|
from _ in Operator("=")
|
|
from node in ConstValueParser()
|
|
select new ConstantNode(identifier, node);
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> ConstDeclarationsParser()
|
|
{
|
|
return (from _ in Keyword("const")
|
|
from tokens in ConstDeclarationParser().SeparatedOrEndBy1(Delimiter(";"))
|
|
select new BlockNode(tokens)).Try(new BlockNode([]));
|
|
}
|
|
|
|
public static IParser<LexicalToken, SyntaxNodeBase> TypeParser()
|
|
{
|
|
return from token in BasicTypeParser()
|
|
select new TypeNode(token);
|
|
}
|
|
|
|
public static IParser<LexicalToken, VariableDeclarationNode> VariableDeclarationParser()
|
|
{
|
|
return from tokens in Satisfy<LexicalToken>(
|
|
token => token.TokenType == LexicalTokenType.Identifier).SeparatedBy1(Delimiter(","))
|
|
from _1 in Delimiter(":")
|
|
from type in TypeParser()
|
|
select new VariableDeclarationNode(tokens, type.Convert<TypeNode>());
|
|
}
|
|
|
|
public static IParser<LexicalToken, BlockNode> VariableDeclarationsParser()
|
|
{
|
|
return (from _ in Keyword("var")
|
|
from nodes in VariableDeclarationParser().SeparatedOrEndBy1(Delimiter(";"))
|
|
select new BlockNode(nodes)).Try(new BlockNode([]));
|
|
}
|
|
|
|
public static IParser<LexicalToken, ProgramBody> ProgramBodyParser()
|
|
{
|
|
return from constant in ConstDeclarationsParser()
|
|
from variables in VariableDeclarationsParser()
|
|
from block in CompoundStatementParser()
|
|
select new ProgramBody(constant.Convert<BlockNode>(), variables, block);
|
|
}
|
|
|
|
public static IParser<LexicalToken, ProgramHead> ProgramHeadParser()
|
|
{
|
|
return from _ in Keyword("program")
|
|
from token in Satisfy<LexicalToken>(token => token.TokenType == LexicalTokenType.Identifier)
|
|
select new ProgramHead(token);
|
|
}
|
|
|
|
public static IParser<LexicalToken, Program> ProgramParser()
|
|
{
|
|
return from head in ProgramHeadParser()
|
|
from _1 in Delimiter(";")
|
|
from body in ProgramBodyParser()
|
|
from _2 in Delimiter(".")
|
|
select new Program(head, body);
|
|
}
|
|
}
|