IFPSTools.NET/LibIFPSCC/Parser/ParserClasses.cs
zc e16c00799d ifpscc: initial commit
libifpscc: initial commit
readme: document ifpscc/libifpscc
license: add credits for ifpscc/libifpscc (derived from code also MIT licensed)
libifps: make additional fields/types public for libifpscc
libifps: fix field documentation for some opcodes
libifps: fix loading functions that are not exported
libifps: allow saving a nonexistant primitive type if the same primitive type was added already
libifps: fix parsing Extended constants
libifps: fix ushort/short being mapped to the wrong types in one table
csproj: set Prefer32Bit=false for release builds
2023-03-28 17:24:19 +01:00

766 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using LexicalAnalysis;
namespace Parsing {
public class ParserThenParser<R1, R2> : IParser<Tuple<R2, R1>> {
public ParserThenParser(IParser<R1> firstParser, IParser<R2> secondParser) {
this.FirstParser = firstParser;
this.SecondParser = secondParser;
}
public IParser<R1> FirstParser { get; }
public IParser<R2> SecondParser { get; }
public RuleCombining Combining => RuleCombining.THEN;
public IParserResult<Tuple<R2, R1>> Parse(ParserInput input) {
var firstResult = this.FirstParser.Parse(input);
if (!firstResult.IsSuccessful) {
return new ParserFailed<Tuple<R2, R1>>(firstResult);
}
var secondResult = this.SecondParser.Parse(firstResult.ToInput());
if (!secondResult.IsSuccessful) {
return new ParserFailed<Tuple<R2, R1>>(secondResult);
}
return ParserSucceeded.Create(Tuple.Create(secondResult.Result, firstResult.Result), secondResult.Environment, secondResult.Source);
}
}
public class ParserThenConsumer<R> : IParser<R> {
public ParserThenConsumer(IParser<R> parser, IConsumer consumer) {
this.Parser = parser;
this.Consumer = consumer;
}
public IParser<R> Parser { get; }
public IConsumer Consumer { get; }
public RuleCombining Combining => RuleCombining.THEN;
public IParserResult<R> Parse(ParserInput input) {
var firstResult = this.Parser.Parse(input);
if (!firstResult.IsSuccessful) {
return new ParserFailed<R>(firstResult);
}
var secondResult = this.Consumer.Consume(firstResult.ToInput());
if (!secondResult.IsSuccessful) {
return new ParserFailed<R>(secondResult);
}
return ParserSucceeded.Create(firstResult.Result, secondResult.Environment, secondResult.Source);
}
}
public class ParserThenTransformer<R1, R2> : IParser<R2> {
public ParserThenTransformer(IParser<R1> parser, ITransformer<R1, R2> transformer) {
this.Parser = parser;
this.Transformer = transformer;
}
public IParser<R1> Parser { get; }
public ITransformer<R1, R2> Transformer { get; }
public RuleCombining Combining => RuleCombining.THEN;
public IParserResult<R2> Parse(ParserInput input) {
var firstResult = this.Parser.Parse(input);
if (!firstResult.IsSuccessful) {
return new ParserFailed<R2>(firstResult);
}
return this.Transformer.Transform(firstResult.Result, firstResult.ToInput());
}
}
public class ConsumerThenParser<R> : IParser<R> {
public ConsumerThenParser(IConsumer consumer, IParser<R> parser) {
this.Consumer = consumer;
this.Parser = parser;
}
public IConsumer Consumer { get; }
public IParser<R> Parser { get; }
public RuleCombining Combining => RuleCombining.THEN;
public IParserResult<R> Parse(ParserInput input) {
var firstResult = this.Consumer.Consume(input);
if (!firstResult.IsSuccessful) {
return new ParserFailed<R>(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<S, R1, R2> : ITransformer<S, Tuple<R2, R1>> {
public TransformerThenParser(ITransformer<S, R1> transformer, IParser<R2> parser) {
this.Transformer = transformer;
this.Parser = parser;
}
public ITransformer<S, R1> Transformer { get; }
public IParser<R2> Parser { get; }
public IParserResult<Tuple<R2, R1>> Transform(S seed, ParserInput input) {
var result1 = this.Transformer.Transform(seed, input);
if (!result1.IsSuccessful) {
return new ParserFailed<Tuple<R2, R1>>(result1);
}
var result2 = this.Parser.Parse(result1.ToInput());
if (!result2.IsSuccessful) {
return new ParserFailed<Tuple<R2, R1>>(result2);
}
return ParserSucceeded.Create(Tuple.Create(result2.Result, result1.Result), result2.Environment, result2.Source);
}
}
public class TransformerThenConsumer<S, R> : ITransformer<S, R> {
public TransformerThenConsumer(ITransformer<S, R> transformer, IConsumer consumer) {
this.Transformer = transformer;
this.Consumer = consumer;
}
public ITransformer<S, R> Transformer { get; }
public IConsumer Consumer { get; }
public IParserResult<R> 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<R>(result2);
}
return ParserSucceeded.Create(result1.Result, result2.Environment, result2.Source);
}
}
public class TransformerThenTransformer<S, I, R> : ITransformer<S, R> {
public TransformerThenTransformer(ITransformer<S, I> firstTransformer, ITransformer<I, R> secondTransformer) {
this.FirstTransformer = firstTransformer;
this.SecondTransformer = secondTransformer;
}
public ITransformer<S, I> FirstTransformer { get; }
public ITransformer<I, R> SecondTransformer { get; }
public IParserResult<R> Transform(S seed, ParserInput input) {
var result1 = this.FirstTransformer.Transform(seed, input);
if (!result1.IsSuccessful) {
return new ParserFailed<R>(result1);
}
return this.SecondTransformer.Transform(result1.Result, result1.ToInput());
}
}
public enum RuleCombining {
NONE,
THEN,
OR
}
/// <summary>
/// A parser consumes one or several tokens, and produces a result.
/// </summary>
public interface IParser<out R> {
IParserResult<R> Parse(ParserInput input);
RuleCombining Combining { get; }
}
public static class Parser {
public static NamedParser<R> Create<R>(String name) =>
new NamedParser<R>(name);
public static IParser<R> Seed<R>(R seed) =>
new AlwaysSucceedingParser<R>(seed);
}
public class NamedParser<R> : IParser<R> {
public NamedParser(String name) {
this.Name = name;
this.Parser = new SetOnce<IParser<R>>();
}
public SetOnce<IParser<R>> Parser { get; }
public void Is(IParser<R> parser) {
this.Parser.Value = parser;
}
public IParserResult<R> 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<R> : IParser<Option<R>> {
public OptionalParser(IParser<R> parser) {
this.Parser = parser;
}
public IParser<R> Parser { get; }
public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<Option<R>> Parse(ParserInput input) {
var result = this.Parser.Parse(input);
if (result.IsSuccessful) {
return ParserSucceeded.Create(new Some<R>(result.Result), result.Environment, result.Source);
}
return ParserSucceeded.Create(new None<R>(), input.Environment, input.Source);
}
}
public class OptionalParserWithDefault<R> : IParser<R> {
public OptionalParserWithDefault(IParser<R> parser, R defaultValue) {
this.Parser = parser;
this.DefaultValue = defaultValue;
}
public IParser<R> Parser { get; }
public R DefaultValue { get; }
public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<R> 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<R> : IParser<R> {
public AlwaysSucceedingParser(R result) {
this.Result = result;
}
public RuleCombining Combining => RuleCombining.NONE;
public R Result { get; }
public IParserResult<R> Parse(ParserInput input) =>
ParserSucceeded.Create(this.Result, input.Environment, input.Source);
}
public class ParserThenCheck<R> : IParser<R> {
public ParserThenCheck(IParser<R> parser, Predicate<IParserResult<R>> predicate) {
this.Parser = parser;
this.Predicate = predicate;
}
public IParser<R> Parser { get; }
public RuleCombining Combining => RuleCombining.NONE;
public Predicate<IParserResult<R>> Predicate { get; }
public IParserResult<R> Parse(ParserInput input) {
var result1 = this.Parser.Parse(input);
if (result1.IsSuccessful && !this.Predicate(result1)) {
return new ParserFailed<R>(result1);
}
return result1;
}
}
public class OrParser<R> : IParser<R> {
public OrParser(ImmutableList<IParser<R>> parsers) {
this.Parsers = parsers;
}
public ImmutableList<IParser<R>> Parsers { get; }
public RuleCombining Combining => RuleCombining.OR;
public IParserResult<R> Parse(ParserInput input) {
IParserResult<R> result = null;
List<IParserFailed> failed = new List<IParserFailed>();
foreach (var parser in this.Parsers) {
result = parser.Parse(input);
if (result.IsSuccessful) {
return result;
} else
{
failed.Add((IParserFailed)result);
}
}
return new ParserFailed<R>(input, failed);
}
}
//public class ParserOrParser<R> : IParser<R> {
// public ParserOrParser(IParser<R> firstParser, IParser<R> secondParser) {
// this.FirstParser = firstParser;
// this.SecondParser = secondParser;
// }
// public IParser<R> FirstParser { get; }
// public IParser<R> SecondParser { get; }
// public RuleCombining Combining => RuleCombining.OR;
// public IParserResult<R> Parse(ParserInput input) {
// var result1 = this.FirstParser.Parse(input);
// if (result1.IsSuccessful) {
// return result1;
// }
// return this.SecondParser.Parse(input);
// }
//}
public class ZeroOrMoreParser<R> : IParser<ImmutableList<R>> {
public ZeroOrMoreParser(IParser<R> parser) {
this.Parser = parser;
}
public RuleCombining Combining => RuleCombining.NONE;
public IParser<R> Parser { get; }
public IParserResult<ImmutableList<R>> Parse(ParserInput input) {
var list = ImmutableList<R>.Empty;
IParserResult<R> 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<R> : IParser<ImmutableList<R>> {
public OneOrMoreParser(IParser<R> parser) {
this.Parser = parser;
}
public RuleCombining Combining => RuleCombining.NONE;
public IParser<R> Parser { get; }
public IParserResult<ImmutableList<R>> Parse(ParserInput input) {
var list = ImmutableList<R>.Empty;
var curResult = this.Parser.Parse(input);
if (!curResult.IsSuccessful) {
return new ParserFailed<ImmutableList<R>>(curResult);
}
IParserResult<R> 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<R> : IParser<ImmutableList<R>>
{
public OneOrMoreParserForEntireUnit(IParser<R> parser)
{
this.Parser = parser;
}
public RuleCombining Combining => RuleCombining.NONE;
public IParser<R> Parser { get; }
public IParserResult<ImmutableList<R>> Parse(ParserInput input)
{
var list = ImmutableList<R>.Empty;
var curResult = this.Parser.Parse(input);
if (!curResult.IsSuccessful)
{
return new ParserFailed<ImmutableList<R>>(curResult);
}
IParserResult<R> 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<ImmutableList<R>>(curResult);
}
}
public class OneOrMoreParserWithSeparator<R> : IParser<ImmutableList<R>> {
public OneOrMoreParserWithSeparator(IConsumer separatorConsumer, IParser<R> elementParser) {
this.SeparatorConsumer = separatorConsumer;
this.ElementParser = elementParser;
}
public RuleCombining Combining => RuleCombining.NONE;
public IConsumer SeparatorConsumer { get; }
public IParser<R> ElementParser { get; }
public IParserResult<ImmutableList<R>> Parse(ParserInput input) {
var list = ImmutableList<R>.Empty;
var curResult = this.ElementParser.Parse(input);
if (!curResult.IsSuccessful) {
return new ParserFailed<ImmutableList<R>>(curResult);
}
IParserResult<R> 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);
}
}
/// <summary>
/// A consumer consumes one or several tokens, and doesn't produce any result.
/// </summary>
public interface IConsumer {
IParserResult Consume(ParserInput input);
}
public class NamedConsumer : IConsumer {
public NamedConsumer() {
this.Consumer = new SetOnce<IConsumer>();
}
public SetOnce<IConsumer> 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 "<Unset Consumer>";
}
}
public class OptionalConsumer : IParser<Boolean> {
public OptionalConsumer(IConsumer consumer) {
this.Consumer = consumer;
}
public RuleCombining Combining => RuleCombining.NONE;
public IConsumer Consumer { get; }
public IParserResult<Boolean> 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<IConsumer> consumers) {
this.Consumers = consumers;
}
public ImmutableList<IConsumer> Consumers { get; }
public IParserResult Consume(ParserInput input) {
IParserResult result = null;
List<IParserFailed> failed = new List<IParserFailed>();
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<ParserEnvironment, ParserEnvironment> transformer) {
this.Transformer = transformer;
}
public Func<ParserEnvironment, ParserEnvironment> Transformer { get; }
public IParserResult Consume(ParserInput input) {
return ParserSucceeded.Create(this.Transformer(input.Environment), input.Source);
}
}
/// <summary>
/// A transformer consumes zero or more tokens, and takes a previous result to produce a new result.
/// </summary>
public interface ITransformer<in S, out R> {
IParserResult<R> Transform(S seed, ParserInput input);
}
public class IdentityTransformer<R> : ITransformer<R, R> {
public IParserResult<R> Transform(R seed, ParserInput input) =>
ParserSucceeded.Create(seed, input.Environment, input.Source);
}
public class SimpleTransformer<S, R> : ITransformer<S, R> {
public SimpleTransformer(Func<S, R> transformFunc) {
this.TransformFunc = transformFunc;
}
public Func<S, R> TransformFunc { get; }
public IParserResult<R> 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<S, R> : ITransformer<S, R> {
public NamedTransformer() {
this.Transformer = new SetOnce<ITransformer<S, R>>();
}
public SetOnce<ITransformer<S, R>> Transformer { get; }
public void Is(ITransformer<S, R> transformer) {
this.Transformer.Value = transformer;
}
public IParserResult<R> 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 "<Unset transformer>";
}
}
public class OptionalTransformer<R> : ITransformer<R, R> {
public OptionalTransformer(ITransformer<R, R> transformer) {
this.Transformer = transformer;
}
public ITransformer<R, R> Transformer { get; }
public IParserResult<R> 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<S, R> : ITransformer<S, R> {
public OrTransformer(ImmutableList<ITransformer<S, R>> transformers) {
this.Transformers = transformers;
}
public ImmutableList<ITransformer<S, R>> Transformers { get; }
public IParserResult<R> Transform(S seed, ParserInput input) {
List<IParserFailed> failed = new List<IParserFailed>();
IParserResult<R> 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<R>(input, failed);
}
}
//public class TransformerOrTransformer<S, R> : ITransformer<S, R> {
// public TransformerOrTransformer(ITransformer<S, R> firstTransformer, ITransformer<S, R> secondTransformer) {
// this.FirstTransformer = firstTransformer;
// this.SecondTransformer = secondTransformer;
// }
// public ITransformer<S, R> FirstTransformer { get; }
// public ITransformer<S, R> SecondTransformer { get; }
// public IParserResult<R> 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<R> : ITransformer<R, R> {
public ResultTransformer(Func<IParserResult<R>, IParserResult<R>> transformFunc) {
this.TransformFunc = transformFunc;
}
public Func<IParserResult<R>, IParserResult<R>> TransformFunc { get; }
public IParserResult<R> Transform(R seed, ParserInput input) =>
this.TransformFunc(ParserSucceeded.Create(seed, input.Environment, input.Source));
}
public class ZeroOrMoreTransformer<R> : ITransformer<R, R> {
public ZeroOrMoreTransformer(ITransformer<R, R> transformer) {
this.Transformer = transformer;
}
public ITransformer<R, R> Transformer { get; }
public IParserResult<R> Transform(R seed, ParserInput input) {
IParserResult<R> curResult = ParserSucceeded.Create(seed, input.Environment, input.Source);
IParserResult<R> lastSuccessfulResult;
do {
lastSuccessfulResult = curResult;
curResult = this.Transformer.Transform(lastSuccessfulResult.Result, lastSuccessfulResult.ToInput());
} while (curResult.IsSuccessful);
return lastSuccessfulResult;
}
}
public class OneOrMoreTransformer<R> : ITransformer<R, R> {
public OneOrMoreTransformer(ITransformer<R, R> transformer) {
this.Transformer = transformer;
}
public ITransformer<R, R> Transformer { get; }
public IParserResult<R> Transform(R seed, ParserInput input) {
var curResult = this.Transformer.Transform(seed, input);
if (!curResult.IsSuccessful) {
return new ParserFailed<R>(curResult);
}
IParserResult<R> 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<String> {
public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<String> Parse(ParserInput input) {
var token = input.Source.First() as TokenIdentifier;
if (token == null) {
return new ParserFailed<String>(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<R> : IParser<R> {
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<R> 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<R>(input);
}
}
public class KeywordParser {
public static KeywordParser<R> Create<R>(KeywordVal keywordVal, R result) =>
new KeywordParser<R>(keywordVal, result);
}
}