From: handa Date: Thu, 13 Aug 2009 01:41:35 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31734c315b41612c726c105f1798f12a5d120997;p=m17n%2Fm17n-lib-cs.git *** empty log message *** --- diff --git a/peg.cs b/peg.cs new file mode 100644 index 0000000..4064434 --- /dev/null +++ b/peg.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +public class Pair { + public A _1 { get; private set; } + public B _2 { get; private set; } + public Pair(A _1, B _2) { + this._1 = _1; + this._2 = _2; + } + public override string ToString() { + return string.Format("({0}, {1})", _1, _2); + } +} +public class ParseResult { + public A Item { get; private set; } + public string Rest { get; private set; } + public ParseResult(A item, string rest) { + Item = item; + Rest = rest; + } + public override string ToString() { + return string.Format("(value = {0}, rest = {1})", Item, Rest); + } +} +public class Parser { + public Func> Target { get; set; } + public Parser(Func> target) { + Target = target; + } + public ParseResult Parse(string input) { + return Target(input); + } + public static Parser Make(Func> target) { + return new Parser(target); + } + public static implicit operator Parser(Parser p) { + return Parser.Make((input) => { + var r = p.Parse(input); + return r != null ? new ParseResult(r.Item, r.Rest) : null; + }); + } + public Parser Or(Parser p2) { + return Make((input) => { + var r = Parse(input); + return r != null ? r : p2.Parse(input); + }); + } + public Parser> Seq(Parser p2) { + return Parser>.Make((input) => { + var r1 = Parse(input); + if(r1 == null) return null; + var r2 = p2.Parse(r1.Rest); + if(r2 == null) return null; + return new ParseResult>( + new Pair(r1.Item, r2.Item), r2.Rest + ); + }); + } + public static Parser operator!(Parser p) { + return p.Not(); + } + public static Parser operator~(Parser p) { + return p.And(); + } + public Parser Not() { + return Parser.Make((input) => { + var r = Parse(input); + return r == null ? new ParseResult(null, input) : null; + }); + } + public Parser And() { + return this.Not().Not(); + } + public Parser Opt() { + return Or(BasicOperations.Str("").Apply((p) => default(A))); + } + public Parser Apply(Func f) { + return Parser.Make((input) => { + var r1 = Parse(input); + return r1 != null ? new ParseResult(f(r1.Item), r1.Rest) : null; + }); + } + public Parser> Rep() { + return Parser>.Make((input) => { + var rs = new List(); + ParseResult r; + while((r = Parse(input)) != null) { + rs.Add(r.Item); + input = r.Rest; + } + return new ParseResult>(rs, input); + }); + } + public Parser> Rep1() { + return this.Seq(this.Rep()).Apply((p) => { + p._2.Add(p._1); + return p._2; + }); + } +} +public class BasicOperations { + public static Parser Any = Parser.Make((input) => { + return input.Length > 0 ? + new ParseResult(input.Substring(0, 1), input.Substring(1)) : null; + }); + public static Parser Str(string param) { + return Parser.Make((input) => { + return input.StartsWith(param) ? + new ParseResult(param, input.Substring(param.Length)) : null; + }); + } + public static Parser Rule(Func> f) { + return Parser.Make((input) => f().Parse(input)); + } +} +public class User : BasicOperations { + public static Parser S = Rule(() => + (~A.Seq(!Str("b"))).Seq(Str("a").Rep1()).Seq(B).Seq(!Str("c")) + ); + public static Parser A = Rule(() => + Str("a").Seq(A.Opt()).Seq(Str("b")) + ); + public static Parser B = Rule(() => + Str("b").Seq(B.Opt()).Seq(Str("c")) + ); + static void Main(string[] args) { + Console.WriteLine("{0}", S.Parse(args[0])); + } +}