using System; using System.Collections.Generic; using System.Linq; using LexicalAnalysis; using AST; using static Parsing.ParserCombinator; using System.Collections.Immutable; namespace Parsing { public partial class CParsers { static CParsers() { SetExpressionRules(); SetDeclarationRules(); SetExternalDefinitionRules(); SetStatementRules(); } public static IParserResult Parse(IEnumerable tokens) => TranslationUnit.Parse(new ParserInput(new ParserEnvironment(), tokens)); public class ConstCharParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenCharConst; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(new IntLiteral(token.Value, TokenInt.IntSuffix.NONE), input.Environment, input.Source.Skip(1)); } } public class ConstIntParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenInt; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(new IntLiteral(token.Val, token.Suffix), input.Environment, input.Source.Skip(1)); } } public class ConstFloatParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenFloat; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(new FloatLiteral(token.Value, token.Suffix), input.Environment, input.Source.Skip(1)); } } public class StringLiteralParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenString; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(new StringLiteral(token.Val), input.Environment, input.Source.Skip(1)); } } public class UnicodeStringLiteralParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenUnicodeString; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(new UnicodeStringLiteral(token.Val), input.Environment, input.Source.Skip(1)); } } public class BinaryOperatorBuilder { public BinaryOperatorBuilder(IConsumer operatorConsumer, Func nodeCreator) { this.OperatorConsumer = operatorConsumer; this.NodeCreator = nodeCreator; } public static BinaryOperatorBuilder Create(IConsumer operatorConsumer, Func nodeCreator) => new BinaryOperatorBuilder(operatorConsumer, nodeCreator); public IConsumer OperatorConsumer { get; } public Func NodeCreator { get; } } // TODO: create a dedicated class for this. public static IParser BinaryOperator(IParser operandParser, params BinaryOperatorBuilder[] builders) { ImmutableList> transformers = builders.Select(builder => Given() .Then(builder.OperatorConsumer) .Then(operandParser) .Then(builder.NodeCreator) ).ToImmutableList(); return operandParser.Then((new OrTransformer(transformers)).ZeroOrMore()); } public static IParser AssignmentOperator( IParser lhsParser, IParser rhsParser, params BinaryOperatorBuilder[] builders ) { var transformers = builders.Select(builder => Given() .Then(builder.OperatorConsumer) .Then(rhsParser) .Then(builder.NodeCreator) ).ToImmutableList(); return lhsParser.Then((new OrTransformer(transformers)).OneOrMore()); } } }