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; } } public class OperatorParser : IParser { private IParser lhsParser; private IParser rhsParser; private readonly ImmutableList builders; private readonly bool needsOne; public OperatorParser(IParser operandParser, IEnumerable builders) : this(operandParser, operandParser, builders) { needsOne = false; } public OperatorParser(IParser lhsParser, IParser rhsParser, IEnumerable builders) { this.lhsParser = lhsParser; this.rhsParser = rhsParser; this.builders = builders.ToImmutableList(); needsOne = true; } public RuleCombining Combining => RuleCombining.THEN; public IParserResult Parse(ParserInput input) { var firstResult = lhsParser.Parse(input); if (!firstResult.IsSuccessful) { return new ParserFailed(firstResult); } return Transform(firstResult.Result, firstResult.ToInput()); } private IParserResult TransformImpl(Expr seed, ParserInput input) { List failed = new List(); foreach (var builder in builders) { var given = ParserSucceeded.Create(seed, input.Environment, input.Source); var result1 = builder.OperatorConsumer.Consume(given.ToInput()); if (!result1.IsSuccessful) { failed.Add(new ParserFailed(result1)); continue; } var result2 = rhsParser.Parse(result1.ToInput()); if (!result2.IsSuccessful) { failed.Add(new ParserFailed(result2)); continue; } var transform = builder.NodeCreator(seed, result2.Result); var ret = ParserSucceeded.Create(transform, result2.Environment, result2.Source); var expr = transform as IStoredLineInfo; if (expr != null) { expr.Copy(ret); } return ret; } return new ParserFailed(input, failed); } public IParserResult Transform(Expr seed, ParserInput input) { IParserResult curResult = needsOne ? TransformImpl(seed, input) : ParserSucceeded.Create(seed, input.Environment, input.Source); if (!curResult.IsSuccessful) return new ParserFailed(curResult); IParserResult lastSuccessfulResult; do { lastSuccessfulResult = curResult; curResult = TransformImpl(lastSuccessfulResult.Result, lastSuccessfulResult.ToInput()); } while (curResult.IsSuccessful); return lastSuccessfulResult; } } public static IParser BinaryOperator(IParser operandParser, params BinaryOperatorBuilder[] builders) => new OperatorParser(operandParser, builders); public static IParser AssignmentOperator( IParser lhsParser, IParser rhsParser, params BinaryOperatorBuilder[] builders ) => new OperatorParser(lhsParser, rhsParser, builders); } }