Changeset 267

Show
Ignore:
Timestamp:
03/21/08 20:44:22 (9 months ago)
Author:
BCS
Message:

updated dparse.d
added some debugging code
a bunch of formatting and commenting
added a "special actions" system (more on that later)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dparser/dparse.d

    r266 r267  
    8181private import glue.templates; 
    8282 
    83 /** generate a tuple of i U's 
    84 */ 
    85 template Tupleof(uint i, U) 
    86 
    87     static if(i == 0) 
    88         alias T!() Tupleof; 
    89     else 
    90     static if(i == 1) 
    91         alias T!(U) Tupleof; 
    92     else 
    93         alias T!(Tupleof!(i-1, U), U) Tupleof; 
    94 
    95  
    96 /** Tuple literal template 
    97 */ 
    98 template T(A...){alias A T;} 
     83 
     84/****************************************************************************** 
     85********* PObject Hieracrcy 
     86******************************************************************************/ 
    9987 
    10088 
     
    10391abstract class PObject 
    10492{ 
     93    /// 
    10594    abstract bool fail(); 
    106 
    107  
    108  
     95 
     96    abstract char[] BaseName(); 
     97
     98 
     99 
     100/************************************************ 
     101    Common base type for ObjectVector types 
     102*/ 
    109103class PObjectVectorBase : PObject 
    110104{ 
     105    char[] BaseName(){return typeof(this).stringof;} 
    111106    abstract char[] string(); 
    112107} 
     
    117112class PObjectVector(uint i) : PObjectVectorBase 
    118113{ 
     114    char[] BaseName(){return typeof(this).stringof;} 
    119115    alias Tupleof!(i,PObject) type; 
    120116    type data; 
     
    128124    this(PObject[i] d) 
    129125    { 
    130         foreach(uint i, v; data) 
    131         { 
    132             data[i] = d[i]; 
    133         } 
     126        foreach(uint j, v; data) 
     127        { 
     128            data[j] = d[j]; 
     129        } 
     130    } 
     131 
     132    PObject[] Get() 
     133    { 
     134        PObject[i] ret; 
     135        foreach(uint j, v; data) 
     136        { 
     137            ret[j] = data[j]; 
     138        } 
     139        return ret.dup; 
    134140    } 
    135141 
     
    143149            default: throw new Error("Out of bound"); 
    144150        } 
     151    } 
     152 
     153    /// Get the j'th item 
     154    PObject GetT(uint j)() 
     155    { 
     156        static if(j<data.length) 
     157            return data[j]; 
     158        else 
     159            static assert(false); 
    145160    } 
    146161 
     
    167182} 
    168183 
     184/************************************************ 
     185    Common base type for BoxObject types 
     186*/ 
    169187class PObjectBoxBase : PObject 
    170188{ 
     189    char[] BaseName(){return typeof(this).stringof;} 
    171190    abstract char[] string(); 
    172191} 
     
    176195class PObjectBox(T,bool str = true) : PObjectBoxBase 
    177196{ 
     197    char[] BaseName(){return typeof(this).stringof~"!("~T.stringof~")";} 
    178198    T t; 
    179199 
     200    /// 
    180201    T Get() { return t; } 
    181202 
     203    /// 
    182204    this(T ti){t=ti;} 
    183205 
    184206    bool fail() { return false; } 
    185207 
     208    /// 
    186209    char[] string() 
    187210    { 
     
    190213            static if(is(T == char[])) 
    191214                return t; 
     215            else static if(is(ToString(t))) 
     216                return ToString(t); 
    192217            else 
    193                 return ToString(t)
     218                return "<<"~T.stringof~">>"
    194219        } 
    195220        else 
     
    203228class PObjectList(T) : PObject 
    204229{ 
     230    char[] BaseName(){return typeof(this).stringof;} 
    205231    debug(TypeReport) pragma(msg, ">>T-"__FILE__~":"~itoa!(__LINE__)~": "~typeof(this).stringof~"!("~T.stringof~")"); 
    206232 
     
    232258    uint Count(){return at;} 
    233259 
     260    /// 
    234261    T[] get() 
    235262    { 
     
    254281} 
    255282 
     283/************************************************ 
     284    List Object that build to the left 
     285*/ 
    256286class PObjectListLeft(T) : PObjectList!(T) 
    257287{ 
     288    char[] BaseName(){return typeof(this).stringof;} 
    258289    debug(TypeReport) pragma(msg, ">>T-"__FILE__~":"~itoa!(__LINE__)~": "~typeof(this).stringof~"!("~T.stringof~")"); 
    259290 
     
    306337class PObjectSet : PObjectList!(PObject) 
    307338{ 
     339    char[] BaseName(){return typeof(this).stringof;} 
    308340    /// Discard some PObjects 
    309341    void Back(uint b) 
     
    312344    } 
    313345} 
     346 
     347 
     348 
     349/************************************************ 
     350    Uniform term to prevent needing to know the 
     351    exact type at compile time. 
     352*/ 
     353interface PInterfaceLeftFactor(T) { PObject InsertLeft(T,PObject); } 
     354 
     355/************************************************ 
     356    PObject that uses T.Action!(str) to process a 
     357    left side term with a Right side term 
     358*/ 
     359class PObjectLeftFactorT(T, int i, char[] str) : PObjectVector!(i), PInterfaceLeftFactor!(T) 
     360{ 
     361    this(PObject[i] d){super(d);} 
     362 
     363    PObject InsertLeft(T that, PObject L) 
     364    { 
     365        PObject[i+1] args; 
     366 
     367        args[1..$] = Get; 
     368        args[0] = L; 
     369 
     370        return that.Action!(str)(args); 
     371    } 
     372} 
     373 
     374 
    314375/************************************************ 
    315376    default fail object 
     
    317378class PObjectFail : PObject 
    318379{ 
     380    char[] BaseName(){return typeof(this).stringof;} 
    319381    char[][] msg; 
    320382 
     
    339401} 
    340402 
     403/************************************************ 
     404    default Pass object 
     405*/ 
     406class PObjectPass : PObject 
     407{ 
     408    char[] BaseName(){return typeof(this).stringof;} 
     409    this() { } 
     410    bool fail() { return false; } 
     411} 
     412 
     413/************************************************ 
     414    default Filler object, returns fail state as instructed 
     415*/ 
    341416class PObjectFill : PObject 
    342417{ 
     418    char[] BaseName(){return typeof(this).stringof;} 
    343419    bool b; 
    344420    this(bool _b){b=_b;} 
     
    353429    uint pos(); 
    354430    void pos(uint); 
    355 
     431    debug(dParse_runtime) void mark(); 
     432
     433 
     434 
     435/****************************************************************************** 
     436******** genaric Template code 
     437******************************************************************************/ 
     438 
     439 
     440/** generate a tuple of i U's 
     441*/ 
     442template Tupleof(uint i, U) 
     443
     444    static if(i == 0) 
     445        alias T!() Tupleof; 
     446    else 
     447    static if(i == 1) 
     448        alias T!(U) Tupleof; 
     449    else 
     450        alias T!(Tupleof!(i-1, U), U) Tupleof; 
     451
     452 
     453/** Tuple literal template 
     454*/ 
     455template T(A...){alias A T;} 
     456 
     457 
     458/****************************************************************************** 
     459******** CTFE functions 
     460******************************************************************************/ 
    356461 
    357462/****************************** 
     
    447552static const char[] test = ReduceWhite("hello"); 
    448553 
     554/********************************* 
     555    Extract # from "$(C,#,NAME)" 
     556*/ 
     557int ExtractCount(char[] str) 
     558{ 
     559    int ret = int.min; 
     560 
     561    if(str.length > 4 && '0' <= str[0] && str[0] <= '9') 
     562    { 
     563        ret = str[0] - '0'; 
     564        for(int i = 1; i<str.length; i++) 
     565        { 
     566            if('0' <= str[i] && str[i] <= '9') 
     567            { 
     568                ret *= 10; 
     569                ret += str[i] - '0'; 
     570            } 
     571            else 
     572                break; 
     573        } 
     574    } 
     575 
     576    return ret; 
     577} 
     578 
     579/********************************* 
     580    Extract NAME from "$(C,#,NAME)" 
     581*/ 
     582char[] ExtractAct(char[] str) 
     583{ 
     584    int c, i; 
     585    for(i=0; i < str.length && c < 2; i++) 
     586        c += (str[i] == ','); 
     587 
     588    str = str[i..$]; 
     589    i=0; 
     590    while(i < str.length && str[i] != ')') i++; 
     591 
     592    return str[0..i]; 
     593} 
     594 
     595/****************************************************************************** 
     596******* Special Action Code 
     597******************************************************************************/ 
     598 
     599/// Pack up stuff in a computed type of PObjectLeftFactorT Object 
     600PObject L_Action(T, char[] str ) (T, PObject[ExtractCount(str[4..$])] i) 
     601{ 
     602    static const int c = ExtractCount(str[4..$]); 
     603    static const char[] n = ExtractAct(str); 
     604    static if(false) pragma(msg, str~" == $(L,"~c.stringof~","~n~")"); 
     605 
     606    return new PObjectLeftFactorT!(T, c, n)(i); 
     607} 
     608 
     609/// Left Process a Leftmost term and right side terms list. 
     610PObject T_Action(T,char[] str) (T that, PObject[1+ExtractCount(str[4..$])] i) 
     611{ 
     612    static const int num = ExtractCount(str[4..$]); 
     613    static const char[] act = ExtractAct(str); 
     614    static if(false) pragma(msg, str~" == $(T,"~num.stringof~","~act~")"); 
     615 
     616    PObject[num] args = i[0..num]; 
     617    auto ret = that.Action!(act)(args); 
     618 
     619    auto listO = cast(PObjectList!(PObject)) i[num];  
     620    auto list = listO.get; 
     621 
     622    foreach(obj; list) 
     623    { 
     624        auto Tobj = cast(PInterfaceLeftFactor!(T))obj; 
     625        ret = Tobj.InsertLeft(that,ret); 
     626    } 
     627    return ret; 
     628} 
     629 
     630template SpecialAction(T,char[] str) 
     631{ 
     632    static if(str.length > 3 && str[0..2] == "$(") 
     633    { 
     634        static if(str[2] == 'T') 
     635            alias T_Action!(T,str) SpecialAction; 
     636        else static if(str[2] == 'L') 
     637            alias L_Action!(T,str) SpecialAction; 
     638        else 
     639            static assert (false, "unknown special action: "~str); 
     640    } 
     641    else 
     642        static assert (false, "unknown special action: "~str); 
     643} 
     644 
     645/****************************************************************************** 
     646******* Parser 
     647******************************************************************************/ 
     648 
     649 
    449650/************************************************ 
    450651    Parse an Identifier name (ID ::= "[A-Za-z][A-Za-z0-9]*") 
     
    473674alias Parse_ID!("   \t!hello world") Parse_ID_test2; 
    474675static assert(!Parse_ID_test2.Match,"Parse_ID failed: "); 
     676} 
     677 
     678 
     679/************************************************ 
     680    Parse an Sepcial action name name 
     681    '$([^)]*)' | 
     682    '$[A-Z][A-Za-z0-9_]*' | 
     683    '$' 
     684*/ 
     685template Parse_SpecialAct (char[] str) 
     686{ 
     687    private const char[] without = DropWhiteF(str); 
     688    //pragma(msg,">>"__FILE__":"~__LINE__.stringof[0..$-1]~": '"~without~\'); 
     689 
     690    static if(without.length == 0 || without[0] != '$') 
     691    { 
     692        pragma(msg,">>"__FILE__":"~__LINE__.stringof[0..$-1]~": unknown Special '"~without~\'); 
     693        const bool Match = false; 
     694    } 
     695    else 
     696    { 
     697        static if( 
     698            without.length == 1 || 
     699            without[1] == ' ' || 
     700            without[1] == '\t' || 
     701            without[1] == '\n' || 
     702            without[1] == '\r' 
     703            ) 
     704        { 
     705            const bool Match = true; 
     706            const char[] Text = without[0..1]; 
     707        } 
     708        else static if(without[1] == '(') 
     709        { 
     710            const bool Match = true; 
     711            const char[] Text = FindChar!(')')(without); 
     712        } 
     713        else static if(without.length > 2 && 'A' <= without[1] && without[1] <= 'Z') 
     714        { 
     715            const bool Match = true; 
     716            const char[] Text = without[0..2] ~ GetID(without[2..$]); 
     717        } 
     718        else 
     719        { 
     720            pragma(msg,">>"__FILE__":"~__LINE__.stringof[0..$-1]~": unknown Special '"~without~\'); 
     721            const bool Match = false; 
     722            const char[] Text = ""; 
     723        } 
     724 
     725        const char[] Remaining = without[Text.length .. $]; 
     726        const char[] Used = str[0 .. $-Remaining.length]; 
     727    } 
     728} 
     729struct UnittetParse_Parse_SpecialAct{ 
     730    // Tests 
     731    static assert(Parse_SpecialAct!("$Ltree ").Match); 
     732    static assert(Parse_SpecialAct!("$(Ltree) ").Match); 
     733    static assert(Parse_SpecialAct!("$ ").Match); 
     734 
     735    //static assert(!Parse_SpecialAct!("$a ").Match); 
     736    //static assert(!Parse_SpecialAct!("a ").Match); 
    475737} 
    476738 
     
    536798        static const bool Match = false; 
    537799} 
    538 struct UnittestParse_Item{ 
    539 // Tests 
    540 alias Parse_Item!(" hello world") Parse_Item_test1; 
    541 static assert(Parse_Item_test1.Match)
    542 static assert(Parse_Item_test1.Text == "hello"); 
    543 static assert(Parse_Item_test1.Used == " hello",       Parse_Item_test1.Used); 
    544 static assert(Parse_Item_test1.Remaining == " world"); 
    545 static assert(Parse_Item_test1.Type == ItemType.single); 
    546  
    547 alias Parse_Item!(" hello +world") Parse_Item_test2; 
    548 static assert(Parse_Item_test2.Match)
    549 static assert(Parse_Item_test2.Text == "hello"); 
    550 static assert(Parse_Item_test2.Used == " hello +",       Parse_Item_test1.Used); 
    551 static assert(Parse_Item_test2.Remaining == "world"); 
    552 static assert(Parse_Item_test2.Type == ItemType.plus); 
    553  
    554 alias Parse_Item!(" hello* +world") Parse_Item_test3; 
    555 static assert(Parse_Item_test3.Match)
    556 static assert(Parse_Item_test3.Text == "hello"); 
    557 static assert(Parse_Item_test3.Used == " hello*",       Parse_Item_test1.Used); 
    558 static assert(Parse_Item_test3.Remaining == " +world"); 
    559 static assert(Parse_Item_test3.Type == ItemType.star); 
    560  
    561 alias Parse_Item!(" hello?*+world") Parse_Item_test4; 
    562 static assert(Parse_Item_test4.Match)
    563 static assert(Parse_Item_test4.Text == "hello"); 
    564 static assert(Parse_Item_test4.Used == " hello?",       Parse_Item_test1.Used); 
    565 static assert(Parse_Item_test4.Remaining == "*+world"); 
    566 static assert(Parse_Item_test4.Type == ItemType.optional); 
    567  
    568 alias Parse_Item!(" \t?*+world") Parse_Item_test5; 
    569 static assert(!Parse_Item_test5.Match)
    570  
     800struct UnittestParse_Item 
     801
     802    // Tests 
     803   alias Parse_Item!(" hello world") Parse_Item_test1
     804   static assert(Parse_Item_test1.Match); 
     805   static assert(Parse_Item_test1.Text == "hello"); 
     806   static assert(Parse_Item_test1.Used == " hello",       Parse_Item_test1.Used); 
     807   static assert(Parse_Item_test1.Remaining == " world"); 
     808    static assert(Parse_Item_test1.Type == ItemType.single); 
     809 
     810   alias Parse_Item!(" hello +world") Parse_Item_test2
     811   static assert(Parse_Item_test2.Match); 
     812   static assert(Parse_Item_test2.Text == "hello"); 
     813   static assert(Parse_Item_test2.Used == " hello +",       Parse_Item_test1.Used); 
     814   static assert(Parse_Item_test2.Remaining == "world"); 
     815    static assert(Parse_Item_test2.Type == ItemType.plus); 
     816 
     817   alias Parse_Item!(" hello* +world") Parse_Item_test3
     818   static assert(Parse_Item_test3.Match); 
     819   static assert(Parse_Item_test3.Text == "hello"); 
     820   static assert(Parse_Item_test3.Used == " hello*",       Parse_Item_test1.Used); 
     821   static assert(Parse_Item_test3.Remaining == " +world"); 
     822    static assert(Parse_Item_test3.Type == ItemType.star); 
     823 
     824   alias Parse_Item!(" hello?*+world") Parse_Item_test4
     825   static assert(Parse_Item_test4.Match); 
     826   static assert(Parse_Item_test4.Text == "hello"); 
     827   static assert(Parse_Item_test4.Used == " hello?",       Parse_Item_test1.Used); 
     828   static assert(Parse_Item_test4.Remaining == "*+world"); 
     829    static assert(Parse_Item_test4.Type == ItemType.optional); 
     830 
     831   alias Parse_Item!(" \t?*+world") Parse_Item_test5
     832    static assert(!Parse_Item_test5.Match); 
    571833} 
    572834 
     
    598860        static const bool Match = false; 
    599861} 
    600 struct UnittestParse_Sequence{ 
    601 // Tests 
    602 alias Parse_Sequence!("Hello world+this?is* good; by") Parse_Sequence_test1; 
    603 static assert(Parse_Sequence_test1.Match); 
    604 static assert(Parse_Sequence_test1.Used == "Hello world+this?is* good", Parse_Sequence_test1.Used); 
    605 static assert(Parse_Sequence_test1.Remaining == "; by"); 
    606 static assert(Parse_Sequence_test1.Clauses[0].Text == "Hello"); 
    607  
    608 alias Parse_Sequence!("+this?is* good; by") Parse_Sequence_test2; 
    609 static assert(!Parse_Sequence_test2.Match); 
    610 
     862struct UnittestParse_Sequence 
     863
     864    // Tests 
     865    alias Parse_Sequence!("Hello world+this?is* good; by") Parse_Sequence_test1; 
     866    static assert(Parse_Sequence_test1.Match); 
     867    static assert(Parse_Sequence_test1.Used == "Hello world+this?is* good", Parse_Sequence_test1.Used); 
     868    static assert(Parse_Sequence_test1.Remaining == "; by"); 
     869    static assert(Parse_Sequence_test1.Clauses[0].Text == "Hello"); 
     870 
     871    alias Parse_Sequence!("+this?is* good; by") Parse_Sequence_test2; 
     872    static assert(!Parse_Sequence_test2.Match); 
     873
     874 
     875 
    611876 
    612877/************************************************ 
     
    615880struct Parse_Case(char[] str) 
    616881{ 
    617     static private alias Parse_ID!(str) act; 
     882    static private alias Parse_ID!(str) act_1; 
     883    static if(act_1.Match) 
     884    { 
     885        alias act_1 act; 
     886        const bool Special = false; 
     887    } 
     888    else 
     889    { 
     890        alias Parse_SpecialAct!(str) act; 
     891        const bool Special = act.Match; 
     892    } 
     893 
    618894    static if(act.Match) 
    619895    { 
     
    633909    else 
    634910        static const bool Match = false; 
    635 
    636 struct UnittestParse_Case{ 
    637 // Tests 
    638 alias Parse_Case!("Act/foo?bar+baz*sig ") Parse_Case_test1; 
    639 static assert(Parse_Case_test1.Match); 
    640 static assert(Parse_Case_test1.Action == "Act"); 
    641 static assert(Parse_Case_test1.Seq == "foo?bar+baz*sig"); 
    642 static assert(Parse_Case_test1.Clauses[0].Text == "foo"); 
    643  
    644 alias Parse_Case!("Act / foo? bar+ baz* sig|") Parse_Case_test2; 
    645 static assert(Parse_Case_test2.Match); 
    646 static assert(Parse_Case_test2.Action == "Act"); 
    647 static assert(Parse_Case_test2.Seq == " foo? bar+ baz* sig"); 
    648 static assert(Parse_Case_test2.Clauses[0].Text == "foo"); 
    649  
    650 alias Parse_Case!("Act foo? / bar+ baz* sig|") Parse_Case_test3; 
    651 static assert(!Parse_Case_test3.Match); 
     911 
     912
     913struct UnittestParse_Case 
     914
     915    // Tests 
     916    alias Parse_Case!("Act/foo?bar+baz*sig ") Parse_Case_test1; 
     917    static assert(Parse_Case_test1.Match); 
     918    static assert(Parse_Case_test1.Action == "Act"); 
     919    static assert(Parse_Case_test1.Seq == "foo?bar+baz*sig"); 
     920    static assert(Parse_Case_test1.Clauses[0].Text == "foo"); 
     921 
     922    alias Parse_Case!("Act / foo? bar+ baz* sig|") Parse_Case_test2; 
     923    static assert(Parse_Case_test2.Match); 
     924    static assert(Parse_Case_test2.Action == "Act"); 
     925    static assert(Parse_Case_test2.Seq == " foo? bar+ baz* sig"); 
     926    static assert(Parse_Case_test2.Clauses[0].Text == "foo"); 
     927 
     928    alias Parse_Case!("Act foo? / bar+ baz* sig|") Parse_Case_test3; 
     929    static assert(!Parse_Case_test3.Match); 
    652930} 
    653931 
     
    707985    } 
    708986} 
    709 struct UnittestParse_Cases{ 
    710 // Tests 
    711 alias Parse_Cases!("Act/foo| For/Bar ") Parse_Cases_test1; 
    712 static assert(Parse_Cases_test1.Match); 
    713 static assert(Parse_Cases_test1.Remaining == ""); 
    714 static assert(Parse_Cases_test1.Used == "Act/foo| For/Bar "); 
    715 static assert(Parse_Cases_test1.Disjuncts[0].Action == "Act"); 
    716 static assert(Parse_Cases_test1.Disjuncts[1].Action == "For"); 
    717  
    718 alias Parse_Cases!("Act/foo| For Bar ") Parse_Cases_test2; 
    719 static assert(Parse_Cases_test2.Match); 
    720 static assert(Parse_Cases_test2.Remaining == "| For Bar "); 
    721 static assert(Parse_Cases_test2.Used == "Act/foo"); 
    722 static assert(Parse_Cases_test2.Disjuncts[0].Action == "Act"); 
     987struct UnittestParse_Cases 
     988
     989    // Tests 
     990    alias Parse_Cases!("Act/foo| For/Bar ") Parse_Cases_test1; 
     991    static assert(Parse_Cases_test1.Match); 
     992    static assert(Parse_Cases_test1.Remaining == ""); 
     993    static assert(Parse_Cases_test1.Used == "Act/foo| For/Bar "); 
     994    static assert(Parse_Cases_test1.Disjuncts[0].Action == "Act"); 
     995    static assert(Parse_Cases_test1.Disjuncts[1].Action == "For"); 
     996 
     997    alias Parse_Cases!("Act/foo| For Bar ") Parse_Cases_test2; 
     998    static assert(Parse_Cases_test2.Match); 
     999    static assert(Parse_Cases_test2.Remaining == "| For Bar "); 
     1000    static assert(Parse_Cases_test2.Used == "Act/foo"); 
     1001    static assert(Parse_Cases_test2.Disjuncts[0].Action == "Act"); 
    7231002} 
    7241003 
     
    7681047    } 
    7691048} 
    770 struct UnittestParse_Rule{ 
    771 //tests 
    772 alias Parse_Rule!("Foo:bar/baz | pig/owl*horse ;  ") Parse_Rule_test1; 
    773 static assert(Parse_Rule_test1.Match); 
    774 static assert(Parse_Rule_test1.Used == "Foo:bar/baz | pig/owl*horse ;"); 
    775 static assert(Parse_Rule_test1.Remaining == "  "); 
    776 static assert(Parse_Rule_test1.Name == "Foo"); 
    777 static assert(Parse_Rule_test1.Disjuncts[0].Action == "bar"); 
    778 static assert(Parse_Rule_test1.Disjuncts[0].Clauses[0].Text == "baz"); 
    779 static assert(Parse_Rule_test1.Disjuncts[1].Action == "pig"); 
     1049struct UnittestParse_Rule 
     1050
     1051    //tests 
     1052    alias Parse_Rule!("Foo:bar/baz | pig/owl*horse ;  ") Parse_Rule_test1; 
     1053    static assert(Parse_Rule_test1.Match); 
     1054    static assert(Parse_Rule_test1.Used == "Foo:bar/baz | pig/owl*horse ;"); 
     1055    static assert(Parse_Rule_test1.Remaining == "  "); 
     1056    static assert(Parse_Rule_test1.Name == "Foo"); 
     1057    static assert(Parse_Rule_test1.Disjuncts[0].Action == "bar"); 
     1058    static assert(Parse_Rule_test1.Disjuncts[0].Clauses[0].Text == "baz"); 
     1059    static assert(Parse_Rule_test1.Disjuncts[1].Action == "pig"); 
    7801060} 
    7811061 
     
    8281108} 
    8291109 
    830 struct UnittestParse_Grammar{ 
    831 alias Parse_Grammar!("Foo:bar/baz | pig/owl*horse ;  ") Parse_Grammar_test1; 
    832  
    833 static assert(Parse_Grammar_test1.Match); 
    834 static assert(Parse_Grammar_test1.Reductions[0].Name == "Foo"); 
    835 static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[0].Action == "bar"); 
    836 static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[0].Clauses[0].Text == "baz"); 
    837 static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[1].Action == "pig"); 
    838 static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[1].Clauses[0].Text == "owl"); 
     1110struct UnittestParse_Grammar 
     1111
     1112    alias Parse_Grammar!("Foo:bar/baz | pig/owl*horse ;  ") Parse_Grammar_test1; 
     1113 
     1114    static assert(Parse_Grammar_test1.Match); 
     1115    static assert(Parse_Grammar_test1.Reductions[0].Name == "Foo"); 
     1116    static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[0].Action == "bar"); 
     1117    static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[0].Clauses[0].Text == "baz"); 
     1118    static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[1].Action == "pig"); 
     1119    static assert(Parse_Grammar_test1.Reductions[0].Disjuncts[1].Clauses[0].Text == "owl"); 
    8391120} 
    8401121 
     
    8941175debug(dParse_runtime) int counter = 0; 
    8951176 
    896 private struct Frame{uint pos; uint rule; uint count;} 
     1177debug(dParse_runtime) int tager = 0; 
     1178 
     1179private struct Frame{uint pos; uint rule; uint count; debug(dParse_runtime) int tag;} 
    8971180 
    8981181PObject Rule(ParserBase,rule)(ParserBase parserBase, IParser p) 
     
    9011184    { 
    9021185        int ind = counter++; 
    903         bool worked = false; 
    904         writef("Try\t(%d)%s...\n", ind, ruleIs); 
    905     } 
    906     debug(dParse_runtime) scope(success) writef("Done\t(%d)%s %s\n", ind, ruleIs, worked); 
    907     debug(dParse_runtime) scope(failure) writef("FAILED\t(%d)%s %s\n", ind, ruleIs, worked); 
    908  
    909     //debug(dparse_verbose) pragma(msg, "Seeking: "~ruleIs); 
     1186        writef("Try\t(%d)%s...\n", ind, rule.Name); 
     1187    } 
     1188    debug(dParse_runtime) scope(success) writef("Done\t(%d)%s\n", ind, rule.Name); 
     1189    debug(dParse_runtime) scope(failure) writef("FAILED\t(%d)%s\n", ind, rule.Name); 
    9101190 
    9111191    static const char[] nameIs = rule.Name; 
     
    9221202    caseLoop: foreach(ci,casev;rule.Disjuncts) 
    9231203    { 
    924         debug(dParse_runtime) writef("*\t(%d)%s:%s...\n", ind, ruleIs,casev.Action); 
     1204        debug(dParse_runtime) writef("*\t(%d)%s:%s...\n", ind, rule.Name,casev.Action); 
    9251205 
    9261206            // dump all checkpoints 
     
    9551235            foreach(index, cl; casev.Clauses) 
    9561236            { 
     1237                debug(dParse_runtime) p.mark(); 
     1238 
    9571239                static if(/*ci == 0 &&*/ index == 0 && nameIs == cl.Text) 
    9581240                    pragma(msg, "Directly recursive rule: "~nameIs) 
     
    9691251                } 
    9701252 
    971  
    972  
    9731253                static if(cl.Type == ItemType.single || cl.Type == ItemType.plus) 
    9741254                { 
    9751255                    // for cases where empty match is not allowed 
    9761256                        // get one 
    977                     debug(dparse_verbose) pragma(msg, "\t\t\t recurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
     1257                    debug(dparse_verbose) pragma(msg, "\t\t\t recurse in from \""~rule.Name~"\" on \""~cl.Text~\"\n); 
    9781258                    auto tmpStore1 = parserBase.Terminal!(cl.Text)(p); 
    979                     debug(dparse_verbose) pragma(msg, "\n\t\t\t recurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
     1259                    assert(tmpStore1 !is null); 
     1260                    debug(dParse_runtime) writef("clause %s (%d) returned a %s fail=%s\n", cl.Text, index, tmpStore1.BaseName, tmpStore1.fail); 
     1261                    debug(dparse_verbose) pragma(msg, "\n\t\t\t recurse out from \""~rule.Name~"\" on \""~cl.Text~\"); 
    9801262 
    9811263                        // test it 
     
    9851267                        { 
    9861268                            store = backups.Pop();  // get checkpoint 
     1269                            debug(dParse_runtime) writef(">>>>>Poped %d\n", store.tag); 
    9871270                            p.pos = store.pos;      // move input steram back 
    9881271                            action = store.rule;    // set point to return to 
     
    10141297                static if(cl.Type != ItemType.single) 
    10151298                { 
     1299                    debug(dParse_runtime) 
     1300                    { 
     1301                        writef("ReAttemping clause %s (%d)...\n", cl.Text, index); 
     1302                        store.tag = tager++; 
     1303                        writef("=======saved  %d @ ", store.tag); 
     1304                        p.mark(); 
     1305                    } 
    10161306                    store.pos = p.pos; 
    10171307                    store.rule = CaseLable!(index).Revert; 
    10181308                    store.count = (cast(PObjectSet)temps[index]).Count(); 
    10191309 
    1020                     debug(dparse_verbose) pragma(msg, "\t\t\trecurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
     1310                    debug(dParse_runtime) writef("<<<<<< pushed  %d\n", store.tag); 
     1311                    backups.Push(store); 
     1312 
     1313                    debug(dparse_verbose) pragma(msg, "\t\t\trecurse in from \""~rule.Name~"\" on \""~cl.Text~\"\n); 
    10211314                    auto tmpStore2 = parserBase.Terminal!(cl.Text)(p); 
    1022                     debug(dparse_verbose) pragma(msg, "\n\t\t\trecurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
     1315                    assert(tmpStore2 ! is null); 
     1316                    debug(dParse_runtime) writef("clause %s (%d) returned a %s fail=%s\n", cl.Text, index, tmpStore2.BaseName, tmpStore2.fail); 
     1317                    debug(dparse_verbose) pragma(msg, "\n\t\t\trecurse out from \""~rule.Name~"\" on \""~cl.Text~\"); 
    10231318 
    10241319                    if(!tmpStore2.fail()) 
    10251320                    { 
    1026                         backups.Push(store); 
    1027  
    10281321                        (cast(PObjectSet)temps[index]).Add(tmpStore2); 
    10291322 
     
    10441337        } 
    10451338        debug(dparse_verbose) pragma(msg,"\tdoing Action \""~casev.Action~\"); 
    1046         debug(dParse_runtime) writef("\treturn (%d)Act '%s'\"", ind, casev.Action); 
    1047         return parserBase.Action!(casev.Action)(temps); 
     1339        debug(dParse_runtime) writef("doing Action \""~casev.Action~\"\n); 
     1340        static if(casev.Special) 
     1341            auto ret = SpecialAction!(ParserBase,casev.Action)(parserBase,temps); 
     1342        else 
     1343            auto ret = parserBase.Action!(casev.Action)(temps); 
     1344        debug(dParse_runtime) writef("Action \""~casev.Action~"\" done\n"); 
     1345        debug(dParse_runtime) writef("\treturn (%d)Act '%s' fail=%s\n", ind, casev.Action, ret.fail); 
     1346        return ret; 
    10481347    } 
    10491348 
    10501349    debug(dParse_runtime) writef("Return (%d)failed\n", ind); 
    10511350    return new PObjectFail("Failed while looking for "~nameIs~\n);//    debug(dparse_verbose) pragma(msg, ">>"__FILE__":"~itoa!(__LINE__)~": is this right?"); 
    1052     debug(dparse_verbose) pragma(msg, "Done: "~ruleIs); 
     1351    debug(dparse_verbose) pragma(msg, "Done: "~rule.Name); 
    10531352} 
    10541353