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 Program Parse(IEnumerable tokens) { IParseResult result = ProgramParser().Parse(new LexicalTokenReadState(tokens)); return result.Value; } public static IParser FactorParser() { // factor -> - factor | + factor IParser minusParser = from _ in Operator("-") from node in FactorParser() select new UnaryOperatorNode(UnaryOperatorType.Minus, node); IParser plusParser = from _ in Operator("+") from node in FactorParser() select new UnaryOperatorNode(UnaryOperatorType.Plus, node); IParser notParser = from _ in Keyword("not") from node in FactorParser() select new UnaryOperatorNode(UnaryOperatorType.Not, node); IParser parenthesisParser = from _1 in Delimiter("(") from node in ExpressionParser() from _2 in Delimiter(")") select node; IParser 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( TrueParser(), FalseParser(), NumberParser(), minusParser, plusParser, notParser, procedureCallParser, VariableParser(), parenthesisParser ); } private static IParser TermRecursively(SyntaxNodeBase left) { // MultiplyOperator -> * | / | div | mod | and IParser 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 TermParser() { // Term -> Factor | Term MultiplyOperator Factor // 消除左递归为 // Term -> Factor Term' // Term' -> MultiplyOperator Factor Term' | ε return FactorParser().Bind(TermRecursively); } private static IParser SimpleExpressionRecursively(SyntaxNodeBase left) { // AddOperator -> + | - | or IParser 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 SimpleExpressionParser() { // SimpleExpression -> Term | SimpleExpression AddOperator Term // 消除左递归为 // SimpleExpression -> Term SimpleExpression' // SimpleExpression' -> AddOperator Term SimpleExpression' | ε return TermParser().Bind(SimpleExpressionRecursively); } public static IParser ExpressionParser() { // RelationOperator -> = | <> | < | <= | > | >= IParser 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() ); } /// /// ExpressionList Parser /// ExpressionList -> Expression | ExpressionList , Expression /// /// public static IParser> ExpressionsParser() => ExpressionParser().SeparatedBy1(Delimiter(",")); public static IParser VariableParser() { return Choice( from token in IdentifierParser() 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 IfParser() { IParser 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 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 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 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 StatementParser() { return Choice( from variable in VariableParser() from _ in Operator(":=") from expression in ExpressionParser() select new AssignNode(variable, expression), ProcedureCallParser(), IfParser(), ForParser(), WhileParser(), CompoundStatementParser() ); } public static IParser 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 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 ConstDeclarationParser() { return from identifier in Satisfy(token => token.TokenType == LexicalTokenType.Identifier) from _ in Operator("=") from node in ConstValueParser() select new ConstantNode(identifier, node); } public static IParser ConstDeclarationsParser() { return (from _ in Keyword("const") from tokens in ConstDeclarationParser().SeparatedOrEndBy1(Delimiter(";")) select new BlockNode(tokens)).Try(new BlockNode([])); } public static IParser ArrayTypeParser() { IParser> 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 TypeParser() { return Choice(ArrayTypeParser(), from token in BasicTypeParser() select new TypeNode(token)); } public static IParser VariableDeclarationParser() { return from tokens in Satisfy( token => token.TokenType == LexicalTokenType.Identifier).SeparatedBy1(Delimiter(",")) from _1 in Delimiter(":") from type in TypeParser() select new VariableDeclarationNode(tokens, type.Convert()); } public static IParser VariableDeclarationsParser() { return (from _ in Keyword("var") from nodes in VariableDeclarationParser().SeparatedOrEndBy1(Delimiter(";")) select new BlockNode(nodes)).Try(new BlockNode([])); } public static IParser> 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> FormalParameterParser() { return (from _ in Delimiter("(") from parameters in ParameterParser().SeparatedBy(Delimiter(";")) from _1 in Delimiter(")") select parameters.Aggregate(new List(), (result, array) => { result.AddRange(array); return result; })).Try([]); } public static IParser 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 SubprogramBodyParser() { return from constant in ConstDeclarationsParser() from variables in VariableDeclarationsParser() from block in CompoundStatementParser() select new SubprogramBody(constant, variables, block); } public static IParser SubprogramParser() { return from head in SubprogramHeadParser() from _ in Delimiter(";") from body in SubprogramBodyParser() select new Subprogram(head, body); } public static IParser 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 ProgramHeadParser() { return from _ in Keyword("program") from token in Satisfy(token => token.TokenType == LexicalTokenType.Identifier) select new ProgramHead(token); } public static IParser ProgramParser() { return from head in ProgramHeadParser() from _1 in Delimiter(";") from body in ProgramBodyParser() from _2 in Delimiter(".") select new Program(head, body); } }