!failを再度入れた(パフォーマンスも良好)
@@ -125,6 +125,8 @@ | ||
125 | 125 | ExecContext_Factory newExecContext_Times( newExecContext_Times_Function); |
126 | 126 | ExecContextRoot *newExecContext_Cut_Function(ExecContext *p_, void *f_, const PPredicate *pred_, VLocal *l) { return new ExecContext_Cut( p_, f_, pred_, l); } |
127 | 127 | ExecContext_Factory newExecContext_Cut( newExecContext_Cut_Function); |
128 | +ExecContextRoot *newExecContext_CutFail_Function(ExecContext *p_, void *f_, const PPredicate *pred_, VLocal *l) { return new ExecContext_CutFail( p_, f_, pred_, l); } | |
129 | +ExecContext_Factory newExecContext_CutFail( newExecContext_CutFail_Function); | |
128 | 130 | |
129 | 131 | ExecContextRoot *newExecContext_Fail_Function(ExecContext *p_, void *f_, const PPredicate *pred_, VLocal *l) { return new ExecContext_Fail( p_, f_, pred_, l); } |
130 | 132 | ExecContext_Factory newExecContext_Fail( newExecContext_Fail_Function); |
@@ -493,6 +495,7 @@ | ||
493 | 495 | factory_map.insert(ExecContext_Factory_Pair( string("counter"), &newExecContext_Counter)); |
494 | 496 | factory_map.insert(ExecContext_Factory_Pair( string("times"), &newExecContext_Times)); |
495 | 497 | factory_map.insert(ExecContext_Factory_Pair( string("!"), &newExecContext_Cut)); |
498 | + factory_map.insert(ExecContext_Factory_Pair( string("!fail"), &newExecContext_CutFail)); | |
496 | 499 | factory_map.insert(ExecContext_Factory_Pair( string("fail"), &newExecContext_Fail)); |
497 | 500 | factory_map.insert(ExecContext_Factory_Pair( string("raise"), &newExecContext_Raise)); |
498 | 501 | factory_map.insert(ExecContext_Factory_Pair( string("next"), &newExecContext_Next)); |
@@ -763,6 +763,15 @@ | ||
763 | 763 | } |
764 | 764 | }; |
765 | 765 | |
766 | +struct ExecContext_CutFail : public ExecContext_Cut { | |
767 | + ExecContext_CutFail(ExecContext *p_, void *f_, const PPredicate *pred_, VLocal *l) : ExecContext_Cut(p_, f_, pred_, l) {} | |
768 | + virtual bool first(PException &excp) { | |
769 | + ExecContext_Cut::first(excp); | |
770 | + p->nobacktrack = true; | |
771 | + return false; | |
772 | + } | |
773 | +}; | |
774 | + | |
766 | 775 | struct ExecContext_Fail : public ExecContextRoot { |
767 | 776 | ExecContext_Fail(ExecContext *p_, void *f_, const PPredicate *pred_, VLocal *l) : ExecContextRoot(p_, f_, pred_, l) {} |
768 | 777 | virtual bool first(PException &excp) { |
@@ -23,12 +23,12 @@ | ||
23 | 23 | |
24 | 24 | // 定数 |
25 | 25 | #ifdef ___X64____ |
26 | -#define VERSION_TEXT "ADP Ver 0.82.0301 X64 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
26 | +#define VERSION_TEXT "ADP Ver 0.82.0306 X64 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
27 | 27 | #else |
28 | 28 | #if _WIN32 |
29 | -#define VERSION_TEXT "ADP Ver 0.82.0301 x86 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
29 | +#define VERSION_TEXT "ADP Ver 0.82.0306 x86 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
30 | 30 | #else |
31 | -#define VERSION_TEXT "ADP Ver 0.82.0301 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
31 | +#define VERSION_TEXT "ADP Ver 0.82.0306 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n" | |
32 | 32 | #endif |
33 | 33 | #endif |
34 | 34 |
@@ -945,24 +945,41 @@ | ||
945 | 945 | if ( p->ncmp("!") ) { |
946 | 946 | body.pop_back(); |
947 | 947 | nobacktrack = true; |
948 | - if ( c.cut.size() == 1 ) { | |
949 | - c.cut.clear(); | |
948 | + Array<PPredicate *>::iterator f = find( c.cut.begin(), c.cut.end(), p); | |
949 | + if ( f != c.cut.end() ) { | |
950 | + c.cut.erase(f); | |
950 | 951 | } |
951 | 952 | } |
953 | + // 最後がfalseでその前が!なら !fail に置き換える | |
954 | + if ( body.size() >= 2 && p->ncmp("fail") ) { | |
955 | + PPredicate *pp = dynamic_cast<PPredicate *>(const_cast<PObject*>(body[body.size()-2])); | |
956 | + if ( pp != 0 && pp->ncmp("!") ) { | |
957 | + PString *n = dynamic_cast<PString*>(const_cast<PObject*>(pp->name)); | |
958 | + if ( n ) { | |
959 | + n->value = "!fail"; | |
960 | + body.pop_back(); | |
961 | + Array<PPredicate *>::iterator f = find( c.cut.begin(), c.cut.end(), pp); | |
962 | + if ( f != c.cut.end() ) { | |
963 | + c.cut.erase(f); | |
964 | + } | |
965 | + } | |
966 | + } | |
967 | + } | |
952 | 968 | } |
953 | 969 | // 途中のカットに関しては引数に保存する変数を入れる |
954 | - for ( size_t i = 0; i < c.vstat.size(); i++ ) { | |
955 | - if ( c.vstat[i] == 3 ) { | |
956 | - PVeriable *v = get_gc()->factory.createObject<PVeriable>(); | |
957 | - v->makeVeriable(c, c.vary[i], false ); | |
958 | - // カットが複数ある場合、本来ならそのカットの位置に対して保存する変数を決定すべきだが | |
959 | - // そんなにカットを使う機会も考えられないのでカット1つを想定して最適化している | |
960 | - for ( size_t j = 0; j < c.cut.size(); j++ ) { | |
961 | - c.cut[j]->addMethodArg(c,0,v); | |
970 | + if ( !c.cut.empty() ) { | |
971 | + for ( size_t i = 0; i < c.vstat.size(); i++ ) { | |
972 | + if ( c.vstat[i] == 3 ) { | |
973 | + PVeriable *v = get_gc()->factory.createObject<PVeriable>(); | |
974 | + v->makeVeriable(c, c.vary[i], false ); | |
975 | + // カットが複数ある場合、本来ならそのカットの位置に対して保存する変数を決定すべきだが | |
976 | + // そんなにカットを使う機会も考えられないのでカット1つを想定して最適化している | |
977 | + for ( size_t j = 0; j < c.cut.size(); j++ ) { | |
978 | + c.cut[j]->addMethodArg(c,0,v); | |
979 | + } | |
962 | 980 | } |
963 | 981 | } |
964 | 982 | } |
965 | - | |
966 | 983 | } |
967 | 984 | return this; |
968 | 985 | } |