using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using LexicalAnalysis; namespace Parsing { public class ParserThenParser : IParser> { public ParserThenParser(IParser firstParser, IParser secondParser) { this.FirstParser = firstParser; this.SecondParser = secondParser; } public IParser FirstParser { get; } public IParser SecondParser { get; } public RuleCombining Combining => RuleCombining.THEN; public IParserResult> Parse(ParserInput input) { var firstResult = this.FirstParser.Parse(input); if (!firstResult.IsSuccessful) { return new ParserFailed>(firstResult); } var secondResult = this.SecondParser.Parse(firstResult.ToInput()); if (!secondResult.IsSuccessful) { return new ParserFailed>(secondResult); } return ParserSucceeded.Create(Tuple.Create(secondResult.Result, firstResult.Result), secondResult.Environment, secondResult.Source); } } public class ParserThenConsumer : IParser { public ParserThenConsumer(IParser parser, IConsumer consumer) { this.Parser = parser; this.Consumer = consumer; } public IParser Parser { get; } public IConsumer Consumer { get; } public RuleCombining Combining => RuleCombining.THEN; public IParserResult Parse(ParserInput input) { var firstResult = this.Parser.Parse(input); if (!firstResult.IsSuccessful) { return new ParserFailed(firstResult); } var secondResult = this.Consumer.Consume(firstResult.ToInput()); if (!secondResult.IsSuccessful) { return new ParserFailed(secondResult); } return ParserSucceeded.Create(firstResult.Result, secondResult.Environment, secondResult.Source); } } public class ParserThenTransformer : IParser { public ParserThenTransformer(IParser parser, ITransformer transformer) { this.Parser = parser; this.Transformer = transformer; } public IParser Parser { get; } public ITransformer Transformer { get; } public RuleCombining Combining => RuleCombining.THEN; public IParserResult Parse(ParserInput input) { var firstResult = this.Parser.Parse(input); if (!firstResult.IsSuccessful) { return new ParserFailed(firstResult); } return this.Transformer.Transform(firstResult.Result, firstResult.ToInput()); } } public class ConsumerThenParser : IParser { public ConsumerThenParser(IConsumer consumer, IParser parser) { this.Consumer = consumer; this.Parser = parser; } public IConsumer Consumer { get; } public IParser Parser { get; } public RuleCombining Combining => RuleCombining.THEN; public IParserResult Parse(ParserInput input) { var firstResult = this.Consumer.Consume(input); if (!firstResult.IsSuccessful) { return new ParserFailed(firstResult); } return this.Parser.Parse(firstResult.ToInput()); } } public class ConsumerThenConsumer : IConsumer { public ConsumerThenConsumer(IConsumer firstConsumer, IConsumer secondConsumer) { this.FirstConsumer = firstConsumer; this.SecondConsumer = secondConsumer; } public IConsumer FirstConsumer { get; } public IConsumer SecondConsumer { get; } public IParserResult Consume(ParserInput input) { var result1 = this.FirstConsumer.Consume(input); if (!result1.IsSuccessful) { return result1; } return this.SecondConsumer.Consume(result1.ToInput()); } } public class TransformerThenParser : ITransformer> { public TransformerThenParser(ITransformer transformer, IParser parser) { this.Transformer = transformer; this.Parser = parser; } public ITransformer Transformer { get; } public IParser Parser { get; } public IParserResult> Transform(S seed, ParserInput input) { var result1 = this.Transformer.Transform(seed, input); if (!result1.IsSuccessful) { return new ParserFailed>(result1); } var result2 = this.Parser.Parse(result1.ToInput()); if (!result2.IsSuccessful) { return new ParserFailed>(result2); } return ParserSucceeded.Create(Tuple.Create(result2.Result, result1.Result), result2.Environment, result2.Source); } } public class TransformerThenConsumer : ITransformer { public TransformerThenConsumer(ITransformer transformer, IConsumer consumer) { this.Transformer = transformer; this.Consumer = consumer; } public ITransformer Transformer { get; } public IConsumer Consumer { get; } public IParserResult Transform(S seed, ParserInput input) { var result1 = this.Transformer.Transform(seed, input); if (!result1.IsSuccessful) { return result1; } var result2 = this.Consumer.Consume(result1.ToInput()); if (!result2.IsSuccessful) { return new ParserFailed(result2); } return ParserSucceeded.Create(result1.Result, result2.Environment, result2.Source); } } public class TransformerThenTransformer : ITransformer { public TransformerThenTransformer(ITransformer firstTransformer, ITransformer secondTransformer) { this.FirstTransformer = firstTransformer; this.SecondTransformer = secondTransformer; } public ITransformer FirstTransformer { get; } public ITransformer SecondTransformer { get; } public IParserResult Transform(S seed, ParserInput input) { var result1 = this.FirstTransformer.Transform(seed, input); if (!result1.IsSuccessful) { return new ParserFailed(result1); } return this.SecondTransformer.Transform(result1.Result, result1.ToInput()); } } public enum RuleCombining { NONE, THEN, OR } /// /// A parser consumes one or several tokens, and produces a result. /// public interface IParser { IParserResult Parse(ParserInput input); RuleCombining Combining { get; } } public static class Parser { public static NamedParser Create(String name) => new NamedParser(name); public static IParser Seed(R seed) => new AlwaysSucceedingParser(seed); } public class NamedParser : IParser { public NamedParser(String name) { this.Name = name; this.Parser = new SetOnce>(); } public SetOnce> Parser { get; } public void Is(IParser parser) { this.Parser.Value = parser; } public IParserResult Parse(ParserInput input) { var result = this.Parser.Value.Parse(input); result.Name = Name; return result; } public String Name { get; } public String Rule => this.Parser.Value.ToString(); public RuleCombining Combining => RuleCombining.NONE; public override String ToString() => this.Name; } public class OptionalParser : IParser> { public OptionalParser(IParser parser) { this.Parser = parser; } public IParser Parser { get; } public RuleCombining Combining => RuleCombining.NONE; public IParserResult> Parse(ParserInput input) { var result = this.Parser.Parse(input); if (result.IsSuccessful) { return ParserSucceeded.Create(new Some(result.Result), result.Environment, result.Source); } return ParserSucceeded.Create(new None(), input.Environment, input.Source); } } public class OptionalParserWithDefault : IParser { public OptionalParserWithDefault(IParser parser, R defaultValue) { this.Parser = parser; this.DefaultValue = defaultValue; } public IParser Parser { get; } public R DefaultValue { get; } public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var result = this.Parser.Parse(input); if (result.IsSuccessful) { return result; } return ParserSucceeded.Create(this.DefaultValue, input.Environment, input.Source); } } public class AlwaysSucceedingParser : IParser { public AlwaysSucceedingParser(R result) { this.Result = result; } public RuleCombining Combining => RuleCombining.NONE; public R Result { get; } public IParserResult Parse(ParserInput input) => ParserSucceeded.Create(this.Result, input.Environment, input.Source); } public class ParserThenCheck : IParser { public ParserThenCheck(IParser parser, Predicate> predicate) { this.Parser = parser; this.Predicate = predicate; } public IParser Parser { get; } public RuleCombining Combining => RuleCombining.NONE; public Predicate> Predicate { get; } public IParserResult Parse(ParserInput input) { var result1 = this.Parser.Parse(input); if (result1.IsSuccessful && !this.Predicate(result1)) { return new ParserFailed(result1); } return result1; } } public class OrParser : IParser { public OrParser(ImmutableList> parsers) { this.Parsers = parsers; } public ImmutableList> Parsers { get; } public RuleCombining Combining => RuleCombining.OR; public IParserResult Parse(ParserInput input) { IParserResult result = null; List failed = new List(); foreach (var parser in this.Parsers) { result = parser.Parse(input); if (result.IsSuccessful) { return result; } else { failed.Add((IParserFailed)result); } } return new ParserFailed(input, failed); } } //public class ParserOrParser : IParser { // public ParserOrParser(IParser firstParser, IParser secondParser) { // this.FirstParser = firstParser; // this.SecondParser = secondParser; // } // public IParser FirstParser { get; } // public IParser SecondParser { get; } // public RuleCombining Combining => RuleCombining.OR; // public IParserResult Parse(ParserInput input) { // var result1 = this.FirstParser.Parse(input); // if (result1.IsSuccessful) { // return result1; // } // return this.SecondParser.Parse(input); // } //} public class ZeroOrMoreParser : IParser> { public ZeroOrMoreParser(IParser parser) { this.Parser = parser; } public RuleCombining Combining => RuleCombining.NONE; public IParser Parser { get; } public IParserResult> Parse(ParserInput input) { var list = ImmutableList.Empty; IParserResult curResult; while ((curResult = this.Parser.Parse(input)).IsSuccessful) { list = list.Add(curResult.Result); input = curResult.ToInput(); } return ParserSucceeded.Create(list, input.Environment, input.Source); } } public class OneOrMoreParser : IParser> { public OneOrMoreParser(IParser parser) { this.Parser = parser; } public RuleCombining Combining => RuleCombining.NONE; public IParser Parser { get; } public IParserResult> Parse(ParserInput input) { var list = ImmutableList.Empty; var curResult = this.Parser.Parse(input); if (!curResult.IsSuccessful) { return new ParserFailed>(curResult); } IParserResult lastSuccessfulResult; do { list = list.Add(curResult.Result); lastSuccessfulResult = curResult; curResult = this.Parser.Parse(lastSuccessfulResult.ToInput()); } while (curResult.IsSuccessful); return ParserSucceeded.Create(list, lastSuccessfulResult.Environment, lastSuccessfulResult.Source); } } public class OneOrMoreParserForEntireUnit : IParser> { public OneOrMoreParserForEntireUnit(IParser parser) { this.Parser = parser; } public RuleCombining Combining => RuleCombining.NONE; public IParser Parser { get; } public IParserResult> Parse(ParserInput input) { var list = ImmutableList.Empty; var curResult = this.Parser.Parse(input); if (!curResult.IsSuccessful) { return new ParserFailed>(curResult); } IParserResult lastSuccessfulResult; do { list = list.Add(curResult.Result); lastSuccessfulResult = curResult; curResult = this.Parser.Parse(lastSuccessfulResult.ToInput()); } while (curResult.IsSuccessful); if (!lastSuccessfulResult.Source.Skip(1).Any()) return ParserSucceeded.Create(list, lastSuccessfulResult.Environment, lastSuccessfulResult.Source); return new ParserFailed>(curResult); } } public class OneOrMoreParserWithSeparator : IParser> { public OneOrMoreParserWithSeparator(IConsumer separatorConsumer, IParser elementParser) { this.SeparatorConsumer = separatorConsumer; this.ElementParser = elementParser; } public RuleCombining Combining => RuleCombining.NONE; public IConsumer SeparatorConsumer { get; } public IParser ElementParser { get; } public IParserResult> Parse(ParserInput input) { var list = ImmutableList.Empty; var curResult = this.ElementParser.Parse(input); if (!curResult.IsSuccessful) { return new ParserFailed>(curResult); } IParserResult lastElementResult; do { list = list.Add(curResult.Result); lastElementResult = curResult; var separatorResult = this.SeparatorConsumer.Consume(curResult.ToInput()); if (!separatorResult.IsSuccessful) { break; } curResult = this.ElementParser.Parse(separatorResult.ToInput()); } while (curResult.IsSuccessful); return ParserSucceeded.Create(list, lastElementResult.Environment, lastElementResult.Source); } } /// /// A consumer consumes one or several tokens, and doesn't produce any result. /// public interface IConsumer { IParserResult Consume(ParserInput input); } public class NamedConsumer : IConsumer { public NamedConsumer() { this.Consumer = new SetOnce(); } public SetOnce Consumer { get; } public void Is(IConsumer consumer) { this.Consumer.Value = consumer; } public IParserResult Consume(ParserInput input) { var result = this.Consumer.Value.Consume(input); result.Name = ToString(); return result; } public override String ToString() { if (this.Consumer.IsSet) { return this.Consumer.Value.ToString(); } return ""; } } public class OptionalConsumer : IParser { public OptionalConsumer(IConsumer consumer) { this.Consumer = consumer; } public RuleCombining Combining => RuleCombining.NONE; public IConsumer Consumer { get; } public IParserResult Parse(ParserInput input) { var result = this.Consumer.Consume(input); if (result.IsSuccessful) { return ParserSucceeded.Create(true, result.Environment, result.Source); } return ParserSucceeded.Create(false, input.Environment, input.Source); } } public class OrConsumer : IConsumer { public OrConsumer(ImmutableList consumers) { this.Consumers = consumers; } public ImmutableList Consumers { get; } public IParserResult Consume(ParserInput input) { IParserResult result = null; List failed = new List(); foreach (var consumer in this.Consumers) { result = consumer.Consume(input); if (result.IsSuccessful) { return result; } else { failed.Add((IParserFailed)result); } } return new ParserFailed(input, failed); } } //public class ConsumerOrConsumer : IConsumer { // public ConsumerOrConsumer(IConsumer firstConsumer, IConsumer secondConsumer) { // this.FirstConsumer = firstConsumer; // this.SecondConsumer = secondConsumer; // } // public IConsumer FirstConsumer { get; } // public IConsumer SecondConsumer { get; } // public IParserResult Consume(ParserInput input) { // var result1 = this.FirstConsumer.Consume(input); // if (!result1.IsSuccessful) { // return new ParserFailed(); // } // return this.SecondConsumer.Consume(result1.ToInput()); // } //} public class EnvironmentTransformer : IConsumer { public EnvironmentTransformer(Func transformer) { this.Transformer = transformer; } public Func Transformer { get; } public IParserResult Consume(ParserInput input) { return ParserSucceeded.Create(this.Transformer(input.Environment), input.Source); } } /// /// A transformer consumes zero or more tokens, and takes a previous result to produce a new result. /// public interface ITransformer { IParserResult Transform(S seed, ParserInput input); } public class IdentityTransformer : ITransformer { public IParserResult Transform(R seed, ParserInput input) => ParserSucceeded.Create(seed, input.Environment, input.Source); } public class SimpleTransformer : ITransformer { public SimpleTransformer(Func transformFunc) { this.TransformFunc = transformFunc; } public Func TransformFunc { get; } public IParserResult Transform(S seed, ParserInput input) { var transform = this.TransformFunc(seed); var ret = ParserSucceeded.Create(transform, input.Environment, input.Source); var expr = transform as IStoredLineInfo; if (expr != null) { expr.Copy(ret); } return ret; } } public class NamedTransformer : ITransformer { public NamedTransformer() { this.Transformer = new SetOnce>(); } public SetOnce> Transformer { get; } public void Is(ITransformer transformer) { this.Transformer.Value = transformer; } public IParserResult Transform(S seed, ParserInput input) { var result = this.Transformer.Value.Transform(seed, input); result.Name = ToString(); return result; } public override String ToString() { if (this.Transformer.IsSet) { return this.Transformer.Value.ToString(); } return ""; } } public class OptionalTransformer : ITransformer { public OptionalTransformer(ITransformer transformer) { this.Transformer = transformer; } public ITransformer Transformer { get; } public IParserResult Transform(R seed, ParserInput input) { var result = this.Transformer.Transform(seed, input); if (result.IsSuccessful) { return result; } return ParserSucceeded.Create(seed, input.Environment, input.Source); } } public class OrTransformer : ITransformer { public OrTransformer(ImmutableList> transformers) { this.Transformers = transformers; } public ImmutableList> Transformers { get; } public IParserResult Transform(S seed, ParserInput input) { List failed = new List(); IParserResult result = null; foreach (var transformer in this.Transformers) { result = transformer.Transform(seed, input); if (result.IsSuccessful) { return result; } else { failed.Add((IParserFailed)result); } } return new ParserFailed(input, failed); } } //public class TransformerOrTransformer : ITransformer { // public TransformerOrTransformer(ITransformer firstTransformer, ITransformer secondTransformer) { // this.FirstTransformer = firstTransformer; // this.SecondTransformer = secondTransformer; // } // public ITransformer FirstTransformer { get; } // public ITransformer SecondTransformer { get; } // public IParserResult Transform(S seed, ParserInput input) { // var result1 = this.FirstTransformer.Transform(seed, input); // if (result1.IsSuccessful) { // return result1; // } // return this.SecondTransformer.Transform(seed, input); // } // public override String ToString() { // return this.FirstTransformer + " | " + this.SecondTransformer; // } //} public class ResultTransformer : ITransformer { public ResultTransformer(Func, IParserResult> transformFunc) { this.TransformFunc = transformFunc; } public Func, IParserResult> TransformFunc { get; } public IParserResult Transform(R seed, ParserInput input) => this.TransformFunc(ParserSucceeded.Create(seed, input.Environment, input.Source)); } public class ZeroOrMoreTransformer : ITransformer { public ZeroOrMoreTransformer(ITransformer transformer) { this.Transformer = transformer; } public ITransformer Transformer { get; } public IParserResult Transform(R seed, ParserInput input) { IParserResult curResult = ParserSucceeded.Create(seed, input.Environment, input.Source); IParserResult lastSuccessfulResult; do { lastSuccessfulResult = curResult; curResult = this.Transformer.Transform(lastSuccessfulResult.Result, lastSuccessfulResult.ToInput()); } while (curResult.IsSuccessful); return lastSuccessfulResult; } } public class OneOrMoreTransformer : ITransformer { public OneOrMoreTransformer(ITransformer transformer) { this.Transformer = transformer; } public ITransformer Transformer { get; } public IParserResult Transform(R seed, ParserInput input) { var curResult = this.Transformer.Transform(seed, input); if (!curResult.IsSuccessful) { return new ParserFailed(curResult); } IParserResult lastSuccessfulResult; do { lastSuccessfulResult = curResult; curResult = this.Transformer.Transform(lastSuccessfulResult.Result, lastSuccessfulResult.ToInput()); } while (curResult.IsSuccessful); return lastSuccessfulResult; } } public class OperatorConsumer : IConsumer { public OperatorConsumer(OperatorVal operatorVal) { this.OperatorVal = operatorVal; } public static IConsumer Create(OperatorVal operatorVal) => new OperatorConsumer(operatorVal); public OperatorVal OperatorVal { get; } public IParserResult Consume(ParserInput input) { if ((input.Source.First() as TokenOperator)?.Val == this.OperatorVal) { return ParserSucceeded.Create(input.Environment, input.Source.Skip(1)); } return new ParserFailed(input); } } public class IdentifierParser : IParser { public RuleCombining Combining => RuleCombining.NONE; public IParserResult Parse(ParserInput input) { var token = input.Source.First() as TokenIdentifier; if (token == null) { return new ParserFailed(input); } return ParserSucceeded.Create(token.Val, input.Environment, input.Source.Skip(1)); } } public class KeywordConsumer : IConsumer { public KeywordConsumer(KeywordVal keywordVal) { this.KeywordVal = keywordVal; } public KeywordVal KeywordVal { get; } public static KeywordConsumer Create(KeywordVal keywordVal) => new KeywordConsumer(keywordVal); public IParserResult Consume(ParserInput input) { if ((input.Source.First() as TokenKeyword)?.Val == this.KeywordVal) { return ParserSucceeded.Create(input.Environment, input.Source.Skip(1)); } return new ParserFailed(input); } } public class KeywordParser : IParser { public KeywordParser(KeywordVal keywordVal, R result) { this.KeywordVal = keywordVal; this.Result = result; } public RuleCombining Combining => RuleCombining.NONE; public KeywordVal KeywordVal { get; } public R Result { get; } public IParserResult Parse(ParserInput input) { if ((input.Source.First() as TokenKeyword)?.Val == this.KeywordVal) { return ParserSucceeded.Create(this.Result, input.Environment, input.Source.Skip(1)); } return new ParserFailed(input); } } public class KeywordParser { public static KeywordParser Create(KeywordVal keywordVal, R result) => new KeywordParser(keywordVal, result); } }