/** * spirit風味パーサ * Authors: みかん屋 */ module mikanya.parser; private import std.stdio; alias wchar ScannerT; /** * スキャナー */ class Scanner { private { ScannerT[] value; size_t index = 0; } /* * constractor */ public { /** * Params: * value = 解析対象列 */ this(ScannerT[] value) { this.value = value; } } /* * propaty */ public { /** * 次の解析対象に移る */ void advance() { ++index; } /** * 解析が終了したら true を返す */ bool atEnd() { return index==value.length?true:false; } /** * 解析対象を一つ取り出す */ ScannerT get() { return value[index]; } size_t pos(){return index;} size_t pos(size_t i){return index + i;} } } /** * パーサー共通のインターフェース */ interface Parser { public { Difference opSub(Parser p); /// Difference opSub(ScannerT c); ///ditto Difference opSub(ScannerT[] c); ///ditto Alternative opOr(Parser p); /// Alternative opOr(ScannerT c); ///ditto Alternative opOr_r(ScannerT c); ///ditto Alternative opOr(ScannerT[] c); ///ditto Alternative opOr_r(ScannerT[] c); ///ditto Sequence opShr(Parser p); /// Sequence opShr(ScannerT c); ///ditto Sequence opShr_r(ScannerT c); ///ditto Sequence opShr(ScannerT[] c); ///ditto Sequence opShr_r(ScannerT[] c); ///ditto Actor opIndex(void function(ScannerT[]) fp); /// Actor opIndex(void delegate(ScannerT[]) dg); ///ditto bool parse(Scanner s); /// } } /** * パーサー基底クラス */ abstract class ParserImpl : Parser { public { /** * Difference パーサーを返す * Returns:Difference パーサー */ Difference opSub(Parser p) { return new Difference(this, p); } /** * ditto */ Difference opSub(ScannerT c) { Character p = new Character(c); return new Difference(this,p); } /** * ditto */ Difference opSub(ScannerT[] c) { String p = new String(c); return new Difference(this,p); } /** * Alternative パーサーを返す * Returns:Alternative パーサー */ Alternative opOr(Parser p) { return new Alternative(this, p); } /** * ditto */ Alternative opOr(ScannerT c) { Character p = new Character(c); return new Alternative(this, p); } /** * ditto */ Alternative opOr_r(ScannerT c) { Character p = new Character(c); return new Alternative(p,this); } /** * ditto */ Alternative opOr(ScannerT[] c) { String p = new String(c); return new Alternative(this, p); } /** * ditto */ Alternative opOr_r(ScannerT[] c) { String p = new String(c); return new Alternative(p,this); } /** * Sequence パーサーを返す * Returns:Sequence パーサー */ Sequence opShr(Parser p) { return new Sequence(this, p); } /** * ditto */ Sequence opShr(ScannerT c) { Character p = new Character(c); return new Sequence(this,p); } /** * ditto */ Sequence opShr_r(ScannerT c) { Character p = new Character(c); return new Sequence(p,this); } /** * ditto */ Sequence opShr(ScannerT[] c) { String p = new String(c); return new Sequence(this,p); } /** * ditto */ Sequence opShr_r(ScannerT[] c) { String p = new String(c); return new Sequence(p,this); } /** * Actor パーサーを返す * Returns:Actor パーサー */ Actor opIndex(void function(ScannerT[]) action) { return new Actor(this,action); } /** * ditto */ Actor opIndex(void delegate(ScannerT[]) action) { return new Actor(this,action); } /** * 構文解析する * * サブクラスでオーバーライドすること * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ bool parse(Scanner scanner) { assert(0); } } } /** * 演算子パーサーの基底クラス */ abstract class Operator : ParserImpl{} /** * 二項演算子パーサーの基底クラス base */ abstract class BinaryOperator : Operator { protected { Parser lhs; Parser rhs; } public { /** * Params: * lhs = 演算子の左側 * rhs = 演算子の右側 */ this(Parser lhs,Parser rhs) { this.lhs = lhs; this.rhs = rhs; } } } /** * 単項算子パーサーの基底クラス base */ abstract class UnaryOperator :Operator { protected { Parser operand; } public { /** * Params: * operand = 被演算子 */ this(Parser operand) { this.operand = operand; } } } /** * Alternative parser * * 選択 */ class Alternative : BinaryOperator { public { /** * Params: * lhs = 演算子の左側 * rhs = 演算子の右側 */ this(Parser lhs, Parser rhs) { super(lhs,rhs); } /** * 構文解析する * * 左側または右側のパーサーが解析が成功したらtrue * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; if(lhs.parse(s)) { return true; }else{ s.pos = pos; if(rhs.parse(s)) { return true; } } s.pos = pos; return false; } } unittest { printf("Alternative unit test\n"); Character cp1 = new Character('a'); Character cp2 = new Character('b'); assert((cp1 | cp2).parse(new Scanner("a"))); assert(('a' | cp2).parse(new Scanner("b"))); assert(!(cp1 | 'a').parse(new Scanner("c"))); printf("Alternative unit test ok\n"); } } /** * Sequence parser * * 順序 */ class Sequence : BinaryOperator { public { /** * Params: * lhs = 演算子の左側 * rhs = 演算子の右側 */ this(Parser lhs, Parser rhs) { super(lhs,rhs); } /** * 構文解析する * * 左側が解析が成功しかつ右側の解析が成功したらtrue * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; if(lhs.parse(s)) { if(rhs.parse(s)) { return true; } } s.pos = pos; return false; } } unittest { printf("Sequence unit test\n"); Character cp1 = new Character('a'); Character cp2 = new Character('b'); assert((cp1 >> cp2).parse(new Scanner("ab"))); assert(('a' >> cp2).parse(new Scanner("ab"))); assert(!(cp1 >> 'b').parse(new Scanner("aa"))); printf("Sequence unit test ok\n"); } } /** * Difference parser * * 差 */ class Difference : BinaryOperator { public { /** * Params: * lhs = 演算子の左側 * rhs = 演算子の右側 */ this(Parser lhs, Parser rhs) { super(lhs,rhs); } /** * 構文解析する * * 左側が解析が成功しかつ右側の解析が失敗したらtrue * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos1 = s.pos; if(lhs.parse(s)) { size_t pos2 = s.pos; s.pos = pos1; if(!rhs.parse(s)) { s.pos = pos2; return true; } } s.pos = pos1; return false; } } unittest { printf("Difference unit test\n"); assert( ((new Range('a','z') - 'c')).parse(new Scanner("a"))); assert(!((new Range('a','z') - 'c')).parse(new Scanner("c"))); assert( (((new Range('a','z') >> new Range('a','z')) - "ab")).parse(new Scanner("aa"))); assert(!(((new Range('a','z') >> new Range('a','z')) - "ab")).parse(new Scanner("ab"))); printf("Difference unit test ok\n"); } } /** * 解析が成功したら登録されたアクションを実行する */ class Actor : UnaryOperator { private { void function(ScannerT[]) fp; void delegate(ScannerT[]) dg; } public { /** * */ this(Parser operand,void function(ScannerT[]) action) { super(operand); this.fp = action; } /** * ditto */ this(Parser operand,void delegate(ScannerT[]) action) { super(operand); this.dg = action; } /** * */ override bool parse(Scanner s) { size_t pos = s.pos; if(s.atEnd) return false; if(operand.parse(s)) { if(fp) fp(s.value[pos..s.pos]); if(dg) dg(s.value[pos..s.pos]); return true; } s.pos = pos; return false; } } } /** * */ abstract class More{} /** * Repeat parser * * 繰り返し */ class Repeat(int MIN,int MAX) : UnaryOperator { private { enum{min = MIN,max = MAX} } public { /** * Params: * operand = 被演算子 */ this(Parser operand) { super(operand); } /** * 構文解析する * * 被演算子が MIN 以上 MAX 以下回成功したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; int cnt = 0; for(;cnt < max;cnt++) if(!operand.parse(s)) break; if(min <= cnt) { return true; } s.pos = pos; return false; } } } /** * ditto */ class Repeat(int MIN,MAX:More) : UnaryOperator { private { enum{min = MIN} } public { /** * Params: * operand = 被演算子 */ this(Parser operand) { super(operand); } /** * 構文解析する * * 被演算子が MIN 回以上成功したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; int cnt = 0; while(1) { if(!operand.parse(s)) break; cnt += 1; } if(min <= cnt) { return true; } s.pos = pos; return false; } } } /** * Repeat parser generator * * 被演算子が MIN 回以上成功したら true * * Params: * MIN = 最低回数 * MAX = 最大回数 * Returns:Repeatクラス */ template rep_p(int MIN,int MAX) { /** * */ Repeat!(MIN,MAX) rep_p(Parser operand) { return new Repeat!(MIN,MAX)(operand); } /** * ditto */ Repeat!(MIN,MAX) rep_p(ScannerT c) { return new Repeat!(MIN,MAX)(new Character(c)); } /** * ditto */ Repeat!(MIN,MAX) rep_p(ScannerT[] s) { return new Repeat!(MIN,MAX)(new String(s)); } } /** * ditto */ template rep_p(int MIN,MAX:More) { /** * */ Repeat!(MIN,MAX) rep_p(Parser operand) { return new Repeat!(MIN,MAX)(operand); } /** * ditto */ Repeat!(MIN,MAX) rep_p(ScannerT c) { return new Repeat!(MIN,MAX)(new Character(c)); } /** * ditto */ Repeat!(MIN,MAX) rep_p(ScannerT[] s) { return new Repeat!(MIN,MAX)(new String(s)); } } /** * Zero or more parse * * 0回以上の出現 */ class ZeroOrMore : UnaryOperator { public { /** * Params: * operand = 被演算子 */ this(Parser operand) { super(new Repeat!(0,More)(operand)); } /** * 構文解析する * * 0回以上出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return true; size_t pos = s.pos; if(operand.parse(s)) { return true; } s.pos = pos; return false; } } } /** * ZeroOrMore parser generator * * Params: * operand = 被演算子 * Returns:ZeroOrMoreクラス */ ZeroOrMore zom_p(Parser operand) { return new ZeroOrMore(operand); } /** * ditto */ ZeroOrMore zom_p(ScannerT c) { return new ZeroOrMore(new Character(c)); } /** * ditto */ ZeroOrMore zom_p(ScannerT[] s) { return new ZeroOrMore(new String(s)); } /** * One or more parse * * 1回以上の出現 */ class OneOrMore : UnaryOperator { public { /** * Params: * operand = 被演算子 */ this(Parser operand) { super(new Repeat!(1,More)(operand)); } /** * 構文解析する * * 1回以上出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; if(operand.parse(s)) { return true; } s.pos = pos; return false; } } } /** * OneOrMore parser generator * * Params: * operand = 被演算子 * Returns:OneOrMoreクラス */ OneOrMore oom_p(Parser operand) { return new OneOrMore(operand); } /** * ditto */ OneOrMore oom_p(ScannerT c) { return new OneOrMore(new Character(c)); } /** * ditto */ OneOrMore oom_p(ScannerT[] s) { return new OneOrMore(new String(s)); } /** * Optional parser */ class Optional : UnaryOperator { public { /** * Params: * operand = 被演算子 */ this(Parser operand) { super(new Repeat!(0,1)(operand)); } /** * 構文解析する * * 0回または1回出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; if(operand.parse(s)) { return true; } s.pos = pos; return false; } } } /** * Optional parser generator * * Params: * operand = 被演算子 * Returns:Optionalクラス */ Optional opt_p(Parser operand) { return new Optional(operand); } /** * ditto */ Optional opt_p(ScannerT c) { return new Optional(new Character(c)); } /** * ditto */ Optional opt_p(ScannerT[] s) { return new Optional(new String(s)); } /** * */ class Postfix { /***/ static ZeroOrMore opMul_r(ScannerT c) { return new ZeroOrMore(new Character(c)); } /**ditto*/ static ZeroOrMore opMul_r(ScannerT[] s) { return new ZeroOrMore(new String(s)); } /**ditto*/ static ZeroOrMore opMul_r(Parser p) { return new ZeroOrMore(p); } /***/ static OneOrMore opAdd_r(ScannerT c) { return new OneOrMore(new Character(c)); } /**ditto*/ static OneOrMore opAdd_r(ScannerT[] s) { return new OneOrMore(new String(s)); } /**ditto*/ static OneOrMore opAdd_r(Parser p) { return new OneOrMore(p); } } alias Postfix _; ///ditto /** * Character parser */ class Character : ParserImpl { private { ScannerT value; } public { /** * Params: * value = 出現するべき文字 */ this(ScannerT value) { this.value = value; } /** * 構文解析する * * 出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; if(value == s.get) { s.advance(); return true; } s.pos = pos; return false; } } unittest { printf("Character unit test\n"); Character cp = new Character('a'); assert(cp.parse(new Scanner("a"))); printf("Character unit test ok\n"); } } /** * Character parser generator * * Params: * value = 出現するべき文字 * Returns:Characterクラス */ Character ch_p(ScannerT value) { return new Character(value); } /** * Range paser */ class Range : ParserImpl { private { ScannerT min,max; } public { /** * Params: * min = 出現するべき文字の下限 * max = 出現するべき文字の上限 */ this(ScannerT min,ScannerT max) { this.min = min; this.max = max; } /** * 構文解析する * * 範囲内の文字が出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; ScannerT c = s.get; if(min <= c && max >= c) { s.advance(); return true; } s.pos = pos; return false; } } } /** * Range paser generator * * Params: * min = 出現するべき文字の下限 * max = 出現するべき文字の上限 * Returns:Range クラス */ Range range_p(ScannerT min,ScannerT max) { return new Range(min,max); } Range range_p(int min,int max) { return new Range(cast(wchar)min,cast(wchar)max); } /** * String parser */ class String : ParserImpl { private { ScannerT[] value; } public { /** * Params: * value = 出現するべき文字列 */ this(ScannerT[] value) { this.value = value; } /** * 構文解析する * * 出現したら true * * Params: * scanner = 解析対象 * Returns:解析できたらtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; foreach(int i, ScannerT c; value) { if(s.atEnd) return false; if(c != s.get) { s.pos = pos; return false; } s.advance(); } return true; } } unittest { printf("String unit test\n"); String sp = new String("hoge"); assert(sp.parse(new Scanner("hoge"))); printf("String unit test ok\n"); } } /** * String parser generator * * Params: * value = 出現するべき文字列 * Returns:Stringクラス */ String str_p(ScannerT[] value) { return new String(value); } /** * Epsilon */ class Epsilon : ParserImpl { private { Parser parser; } public { this(){} this(Parser p) { parser = p; } /** * 構文解析する * スキャナは前進しない * Params: * scanner = 解析対象 * Returns:常にtrue */ override bool parse(Scanner s) { if(s.atEnd) return false; size_t pos = s.pos; bool result; result = parser.parse(s); s.pos = pos; return result; } } } /** * Epsilon parser generator * * Returns:Epsilonクラス */ Epsilon eps_p() { return new Epsilon; } Epsilon eps_p(Parser p) { return new Epsilon(p); } class Rule : ParserImpl { private { Parser parser; } public { /** * 構文 * * Params: * value = 構文 */ void opAssign (Parser p) { parser = p; } /** * 構文解析する * * Params: * scanner = 解析対象 * Returns:解析成功 true */ override bool parse(Scanner s) { size_t pos = s.pos; if(s.atEnd) return false; if(parser.parse(s)) return true; s.pos = pos; return false; } bool parse(ScannerT[] s) { return parse(new Scanner(s)); } } }