自由モノイドプログラミング言語の作成(MonIter C#版 バージョン1.1)
C# のコードを生成するために構文の要素を変更します。C# の関数の定義ではパラメーターに型を指定しなければならないのでその部分を変更します。全体の構文は同じです。
以前 C# のコードを実行する方法がないと書きましたが、「Roslyn for Scripting」というものを使えばできるようです。まだできていませんのでできたら公開したいと思います。
構文解析のコードは「拡張メソッド」を使うと少しまとめることができるようです。
拡張メソッドのクラス
以下のようなクラスを作ると「拡張メソッド」を使うことができます。
internal static class ParserExtension { public static Parser<T> ParenEnclosed<T>(this Parser<T> parser) { return parser.Contained(Parse.Char('(').Token(), Parse.Char(')').Token()); } public static Parser<IEnumerable<T>> ListBy<T>(this Parser<T> parser, char sep) { return parser.DelimitedBy(Parse.Char(sep).Token()); } }
構文解析のクラス
「拡張メソッド」を使って書き直します。
internal class MonParser { private static readonly Parser<Expression> ParseExpression = Parse.Ref(() => ParseExpression_); private static readonly Parser<Number> ParseNumber = from num in Parse.Decimal.Token() select DomainExpression.Number(num); private static readonly Parser<Identifier> ParseIdentifier = from name in Parse.Identifier(Parse.Letter, Parse.LetterOrDigit.Or(Parse.Char('_'))).Token() select DomainExpression.Identifier(name); private static readonly Parser<ParameterName> ParseParameterName = from name in Parse.Identifier(Parse.Letter, Parse.LetterOrDigit.Or(Parse.Char('_'))).Token() select Expression.ParameterName(name); private static readonly Parser<DomainTerm> ParseDomainTerm = ((Parser<DomainTerm>)ParseIdentifier).Or(ParseNumber); private static readonly Parser<DomainExpression> ParseDomainExpression = from list in ParseDomainTerm.ListBy('+') select new DomainExpression(list); private static readonly Parser<IEnumerable<DomainExpression>> ParseDomainExpressionList = ParseDomainExpression.ListBy(','); private static readonly Parser<DomainFunction> ParseDomainFunction = from name in ParseIdentifier from list in ParseDomainExpressionList.ParenEnclosed() select Expression.DomainFunction(name, list); private static readonly Parser<IEnumerable<Expression>> ParseExpressionList = ParseExpression.ListBy(','); private static readonly Parser<Function> ParseFunction = from pr in Parse.Char('$').Token() from name in ParseIdentifier from list in ParseExpressionList.ParenEnclosed() select Expression.Function(name, list); private static readonly Parser<Term> ParseTerm = ((Parser<Term>)ParseFunction).Or(ParseDomainFunction).Or(ParseDomainExpression); private static readonly Parser<Expression> ParseExpression_ = from list in ParseTerm.ListBy('&') select new Expression(list); private static readonly Parser<Statement> ParseExpressionStatement = from exp in ParseExpression select Statement.ExpressionStatement(exp); private static readonly Parser<IEnumerable<ParameterName>> ParseParameterList = ParseParameterName.ListBy(','); private static readonly Parser<Definition> ParseDefinition = from pr in Parse.String("def").Token() from name in ParseIdentifier from list in ParseParameterList.ParenEnclosed() from eq in Parse.Char('=').Token() from exp in ParseExpression select Statement.Definition(name, list, exp); private static readonly Parser<Statement> ParseStatement = ParseDefinition.Or(ParseExpressionStatement); private static readonly Parser<Prog> ParseProgram = from list in ParseStatement.ListBy(';') select new Prog(list); public static Prog ParseProg(string src) { return ParseProgram.Parse(src); } }