Changeset 56

Show
Ignore:
Timestamp:
09/11/07 11:02:42 (5 years ago)
Author:
BCS
Message:

Lots of updates!!
firstly all the debugs stuff now uses debug identifiers:

dparse_verbose for compile time stuff
dParse_runtime for run time stuff
dparse_unittest to turn on the main unittest

also a bunch of updates to the asserts (they now all have messages)
a few more logging line salted around
at the current line 1000 a 'this.' got removed so that parser can be created at module scope (sometimes this generates like errors, I'll have to talk to W on this one)
It will now (at compile time) warn you about some unusable grammars like A ::= A B;
there is now a waning about unparsed data in the input.
the struct Frame was moved to get rid of some issues with duplicate code. see "Well that was stupid of me" in the main NG (9/10/07)
rearranged the PObject hierarchy, adding:
PObjectFill // pass/fail, no content object
PObjectList // generic list builder
PObjectListLeft // derived from PObjectList but adds to the left side
PObject.fail is now abstract (and should have been all along)

Most of these come from typing to get a big grammar working so expect more to come, including some preprocessor apps.

Files:

Legend:

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

    r53 r56  
    6161   Value v = cast(Value)set.Parser(a); 
    6262 
    63    assert(v !is null); 
     63   assert(v !is null,"ERR0R"); 
    6464   writef("%d\n", v.value); 
    6565} 
     
    123123abstract class PObject 
    124124{ 
    125     bool fail(); 
     125    abstract bool fail(); 
    126126} 
    127127 
     
    194194/** 
    195195*/ 
    196 class PObjectBox(T) : PObjectBoxBase 
     196class PObjectBox(T,bool str = true) : PObjectBoxBase 
    197197{ 
    198198    T t; 
     
    206206    char[] string() 
    207207    { 
    208         static if(is(T == char[])) 
    209             return t; 
     208        static if(str) 
     209        { 
     210            static if(is(T == char[])) 
     211                return t; 
     212            else 
     213                return ToString(t); 
     214        } 
    210215        else 
    211             return std.string.toString(t)
     216            return "<<"~T.stringof~">>"
    212217    } 
    213218} 
    214219//typedef PObjectVector!(5) Five; 
     220 
     221/** 
     222*/ 
     223class PObjectList(T) : PObject 
     224{ 
     225    T[] list; 
     226    int at=0; 
     227 
     228    this(){ list = null; } 
     229 
     230    this(T ti) 
     231    { 
     232        static if(is(T :Object)) assert(ti !is null); 
     233        list = new T[5]; 
     234        list[at] = ti; 
     235        at++; 
     236 
     237    } 
     238 
     239    /// Add a T 
     240    uint Add(T ti) 
     241    { 
     242        static if(is(T :Object)) assert(ti !is null); 
     243        if(list.length <= at) list.length = at + 5; 
     244        list[at] = ti; 
     245        at++; 
     246        return at-1; 
     247    } 
     248 
     249    /// return the number of items stored 
     250    uint Count(){return at;} 
     251 
     252    T[] get() 
     253    { 
     254        return list[0..at]; 
     255    } 
     256 
     257    bool fail() { return false; } 
     258} 
     259 
     260class PObjectListLeft(T) : PObjectList!(T) 
     261{ 
     262    this(T t){super(t);} 
     263    this(){} 
     264     
     265    /// Add a T 
     266    uint Add(T ti) 
     267    { 
     268        static if(is(T :Object)) assert(ti !is null); 
     269 
     270        if(list.length <= at) 
     271        { 
     272            auto t = list[$-at..$].dup; 
     273            list.length = at + 5; 
     274            list[$-at..$] = t; 
     275        } 
     276        list[$-1-at] = ti; 
     277        at++; 
     278        return at-1; 
     279    } 
     280 
     281    T[] get() 
     282    { 
     283        return list[$-at..$]; 
     284    } 
     285} 
     286 
     287unittest 
     288{ 
     289    writef("unittest@"__FILE__":"~itoa!(__LINE__)~\n); 
     290     
     291    auto o = new PObjectListLeft!(int); 
     292    o.Add(1); 
     293    o.Add(2); 
     294    o.Add(3); 
     295    o.Add(4); 
     296    o.Add(5); 
     297    o.Add(6); 
     298 
     299    assert(o.get == [6,5,4,3,2,1], "PObjectListLeft failed"); 
     300} 
    215301 
    216302 
     
    219305    A sub class of PObject that is used for repeated reductions 
    220306*/ 
    221 class PObjectSet : PObject 
    222 
    223     PObject[] set; 
    224     this(){ set = null; } 
    225  
    226     /// Add a PObject 
    227     uint Add(PObject o) 
    228     { 
    229         uint ret = set.length; 
    230         set ~= o; 
    231         return ret; 
    232     } 
    233  
    234     /// return the number of items stored 
    235     uint Count(){return set.length;} 
    236  
     307class PObjectSet : PObjectList!(PObject) 
     308
    237309    /// Discard some PObjects 
    238310    void Back(uint b) 
    239311    { 
    240         set.length = b; 
    241     } 
    242  
    243     bool fail() { return false; } 
     312        at = b; 
     313    } 
    244314} 
    245315 
     
    269339 
    270340    bool fail() { return true; } 
     341} 
     342 
     343class PObjectFill : PObject 
     344{ 
     345    bool b; 
     346    this(bool _b){b=_b;} 
     347    bool fail(){return b;} 
    271348} 
    272349 
     
    327404 
    328405 
    329 char[] ReduceWhite(char[] str) 
     406public char[] ReduceWhite(char[] str) 
    330407{ 
    331408    bool pass = true; 
     
    696773        static const char[] Remaining = str[Used.length .. $]; 
    697774 
     775        // Get a given rule 
    698776        template Rule(char[] str) 
    699777        { 
     
    750828    const int Revert = i*(Places.max+1) + Places.Revert; 
    751829    const int Start  = i*(Places.max+1) + Places.Start; 
    752 //  pragma(msg, ">> CaseLabel!("~itoa!(i)~") = { Back : "~itoa!(Back)~", Revert : "~itoa!(Revert)~", Start : "~itoa!(Start)~"}"); 
     830//  debug(dparse_verbose) pragma(msg, ">> CaseLabel!("~itoa!(i)~") = { Back : "~itoa!(Back)~", Revert : "~itoa!(Revert)~", Start : "~itoa!(Start)~"}"); 
    753831} 
    754832 
     
    760838SEQUENCE : ID SEQUENCE | ; 
    761839*/ 
    762 debug int counter = 0; 
    763  
    764 template Parser(char[] start, char[] rules) 
     840debug(dParse_runtime) int counter = 0; 
     841 
     842private struct Frame{uint pos; uint rule; uint count;} 
     843 
     844template ParserT(char[] start, char[] rules) 
    765845{ 
    766846    private alias Parse_Grammar!(rules) grammar; 
    767847    static assert(grammar.Match); 
    768848 
     849    static if(grammar.Match && DropWhiteF(grammar.Remaining).length != 0) 
     850        pragma(msg, "Unparsed data: "~DropWhiteF(grammar.Remaining)); 
     851 
    769852    PObject Rule(char[] ruleIs)(IParser p) 
    770853    { 
    771         debug 
     854        debug(dParse_runtime) 
    772855        { 
    773856            int ind = counter++; 
    774857            bool worked = false; 
    775             std.stdio.writef("Try\t(%d)%s...\n", ind, ruleIs); 
    776         } 
    777         debug scope(success) std.stdio.writef("Done\t(%d)%s %s\n", ind, ruleIs, worked); 
    778         debug scope(failure) std.stdio.writef("FAILED\t(%d)%s %s\n", ind, ruleIs, worked); 
    779  
    780         pragma(msg, "Seeking: "~ruleIs); 
    781  
    782         struct Frame{uint pos; uint rule; uint count;} 
     858            writef("Try\t(%d)%s...\n", ind, ruleIs); 
     859        } 
     860        debug(dParse_runtime) scope(success) writef("Done\t(%d)%s %s\n", ind, ruleIs, worked); 
     861        debug(dParse_runtime) scope(failure) writef("FAILED\t(%d)%s %s\n", ind, ruleIs, worked); 
     862 
     863        debug(dparse_verbose) pragma(msg, "Seeking: "~ruleIs); 
     864 
    783865        Stack!(Frame) backups; 
    784866        Frame store; 
     
    787869        { 
    788870            alias grammar.Rule!(ruleIs).Is rule; 
    789             pragma(msg,"Build: \""~rule.Name~"\"" ); 
     871            debug(dparse_verbose) pragma(msg,"Build: \""~rule.Name~"\"" ); 
    790872                        // record start location 
    791873                    uint start = p.pos; 
     
    794876                    caseLoop: foreach(ci,casev;rule.Disjuncts) 
    795877                    { 
    796                         debug std.stdio.writef("*\t(%d)%s:%s...\n", ind, ruleIs,casev.Action); 
     878                        debug(dParse_runtime) writef("*\t(%d)%s:%s...\n", ind, ruleIs,casev.Action); 
    797879 
    798880                            // dump all checkpoints 
     
    800882 
    801883                            // return to start location 
    802                         p.pos = start; 
     884                        static if(ci != 0) 
     885                        { 
     886                            debug(dParse_runtime) writef("backing\t (%d):%d\n", ind ,start); 
     887                            p.pos = start; 
     888                        } 
    803889 
    804890                            // allocate storage for returns 
     
    807893                        static assert(count == temps.length); 
    808894 
    809                         // pragma(msg, "ICE from "~rule.name); 
    810                         pragma(msg, "\tfor \""~rule.Name~"\" doing case #"~itoa!(ci)~" action = \""~casev.Action~"\", length = "~itoa!(count)); 
     895                        debug(dparse_verbose) pragma(msg, "\tfor \""~rule.Name~"\" doing case #"~itoa!(ci)~" action = \""~casev.Action~"\", length = "~itoa!(count)); 
    811896 
    812897                        static const int FirstCase = -1; 
     
    823908                            foreach(index, cl; casev.Clauses) 
    824909                            { 
     910                                static if(/*ci == 0 &&*/ index == 0 && ruleIs == cl.Text) pragma(msg, "Directly recursive rule: "~ruleIs) 
    825911                                    // static stuff 
    826912 
    827                                 debug std.stdio.writef("Attemping clause %s (%d)...\n", cl.Text, index); 
    828  
    829                                 pragma(msg, "\t\tgenerating clause: \""~cl.Text~"\" ("~itoa!(index)~")"); 
     913                                debug(dParse_runtime) writef("Attemping clause %s (%d)...\n", cl.Text, index); 
     914 
     915                                debug(dparse_verbose) pragma(msg, "\t\tgenerating clause: \""~cl.Text~"\" ("~itoa!(index)~")"); 
    830916 
    831917                                static if(cl.Type != ItemType.single) 
     
    841927                                    // for cases where empty match is not allowed 
    842928                                        // get one 
    843                                     pragma(msg, "\t\t\t recurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
     929                                    debug(dparse_verbose) pragma(msg, "\t\t\t recurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
    844930                                    auto tmpStore1 = Rule!(cl.Text)(p); 
    845                                     pragma(msg, "\n\t\t\t recurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
     931                                    debug(dparse_verbose) pragma(msg, "\n\t\t\t recurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
    846932 
    847933                                        // test it 
     
    884970                                    store.count = (cast(PObjectSet)temps[index]).Count(); 
    885971 
    886                                     pragma(msg, "\t\t\trecurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
     972                                    debug(dparse_verbose) pragma(msg, "\t\t\trecurse in from \""~ruleIs~"\" on \""~cl.Text~\"\n); 
    887973                                    auto tmpStore2 = Rule!(cl.Text)(p); 
    888                                     pragma(msg, "\n\t\t\trecurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
     974                                    debug(dparse_verbose) pragma(msg, "\n\t\t\trecurse out from \""~ruleIs~"\" on \""~cl.Text~\"); 
    889975 
    890976                                    if(!tmpStore2.fail()) 
     
    909995                            } 
    910996                        } 
    911                         pragma(msg,"\tdoing Action \""~casev.Action~\"); 
    912                         return this.Action!(casev.Action)(temps); 
     997                        debug(dparse_verbose) pragma(msg,"\tdoing Action \""~casev.Action~\"); 
     998                        debug(dParse_runtime) writef("\treturn (%d)Act '%s'\"", ind, casev.Action); 
     999 
     1000                        return Action!(casev.Action)(temps); 
    9131001                    } 
    914  
    915                     return new PObjectFail("Failed while looking for "~ruleIs~\n);//    pragma(msg, ">>"__FILE__":"~itoa!(__LINE__)~": is this right?"); 
     1002                    debug(dParse_runtime) writef("Return (%d)failed\n", ind); 
     1003 
     1004                    return new PObjectFail("Failed while looking for "~ruleIs~\n); 
    9161005                } 
    9171006                else 
    9181007                { 
    919             pragma(msg, \"~ruleIs~"\" must be a terminal looking for it..."); 
    920             debug std.stdio.writef("T\t(%d)%s...\n", ind, ruleIs); 
    921 //          static assert(is(Terminal!(ruleIs)),"Terminal \""~ruleIs~"\" not found"); 
     1008            debug(dparse_verbose) pragma(msg, \"~ruleIs~"\" must be a terminal looking for it..."); 
     1009            debug(dParse_runtime) writef("T\t(%d)%s...\n", ind, ruleIs); 
     1010 
    9221011            auto ret = Terminal!(ruleIs)(p); 
    9231012            assert(ret !is null); 
    924             debug worked = !ret.fail; 
     1013            debug(dParse_runtime) worked = !ret.fail; 
     1014 
     1015            debug(dParse_runtime) writef("Return (%d)terminal\n", ind); 
    9251016            return ret; 
    9261017        } 
    9271018 
    928         pragma(msg, "Done: "~ruleIs); 
     1019        debug(dparse_verbose) pragma(msg, "Done: "~ruleIs); 
    9291020    } 
    9301021    alias Rule!(start) Parser; 
     
    9761067    unittest // unittest Stack!(T) 
    9771068    { 
     1069        writef("unittest@"__FILE__":"~itoa!(__LINE__)~"!("~T.stringof~")\n"); 
     1070 
    9781071        Stack!(int) st; 
    9791072        int i; 
     
    9971090} 
    9981091 
    999 // Unittest code 
    1000 unittest 
    1001 
    1002     P p; 
    1003     data d = new data; 
    1004     char[][] pass = 
    1005         [ 
    1006         "BB"[],         //root > next baz > (baz) baz) 
    1007         "HOB",          //root > next baz > (owl* horse owl) baz > (() horse owl) baz 
    1008         "OHOB",         //root > next baz > (owl* horse owl) baz > ((owl) horse owl) baz 
    1009         "OOHOB",        //root > next baz > (owl* horse owl) baz > ((owl owl) horse owl) baz 
    1010         "BHO",          //root > baz horse owl 
    1011         "CHB",          //root > cat horse+ owl* baz > cat (horse) () baz 
    1012         "CHOB",         //root > cat horse+ owl* baz > cat (horse) (owl) baz 
    1013         "CHHOB",        //root >  cat horse+ owl* baz > cat (horse horse) (owl) baz 
    1014         "CCC",          //root > cat* cat cat > (cat) cat cat 
    1015         "KQKQKQKQQKQK", // root > twin* car > (twin twin twin) (car) > ((king qween) (king qween) (king qween)) (king qween qween king) 
    1016         ], 
    1017         fail = 
    1018         [ 
    1019         "BHHO"[], 
    1020         "COB", 
    1021         "CB", 
    1022         "CHHOOB", 
    1023         ]; 
    1024  
    1025     foreach(char[] passTest; pass) 
    1026     { 
    1027         d.dat = passTest; 
    1028         d.i=0; 
    1029         assert(!p.Parser(d).fail, \"~passTest~"\" failed to parse"); 
    1030     } 
    1031  
    1032     foreach(char[] failTest; fail) 
    1033     { 
    1034         d.dat = failTest; 
    1035         d.i=0; 
    1036          assert(p.Parser(d).fail, \"~failTest~"\" failed to fail to parse"); 
    1037     } 
    1038 
    1039  
    1040 struct P 
    1041 
    1042     PObject Terminal(char[] str : "baz")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'B') return new PObjectFail; d.i++; return new PObjectBox!(char)('B');} 
    1043     PObject Terminal(char[] str : "owl")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'O') return new PObjectFail; d.i++; return new PObjectBox!(char)('O');} 
    1044     PObject Terminal(char[] str : "horse")(IParser i) {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'H') return new PObjectFail; d.i++; return new PObjectBox!(char)('H');} 
    1045     PObject Terminal(char[] str : "cat")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'C') return new PObjectFail; d.i++; return new PObjectBox!(char)('C');} 
    1046     PObject Terminal(char[] str : "king")(IParser i)  {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'K') return new PObjectFail; d.i++; return new PObjectBox!(char)('K');} 
    1047     PObject Terminal(char[] str : "qween")(IParser i) {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'Q') return new PObjectFail; d.i++; return new PObjectBox!(char)('Q');} 
    1048  
    1049     PObject Action(char[] str : "bar") (PObject[1] i){return new PObjectVector!(1)(i);} 
    1050     PObject Action(char[] str : "beer")(PObject[2] i){return new PObjectVector!(2)(i);} 
    1051     PObject Action(char[] str : "pig") (PObject[3] i){return new PObjectVector!(3)(i);} 
    1052     PObject Action(char[] str : "keg") (PObject[4] i){return new PObjectVector!(4)(i);} 
    1053  
    1054     const char[] gram = " 
    1055         next : 
    1056             bar / baz | 
    1057             pig / owl * horse owl ; 
    1058         root : 
    1059             beer / next baz | 
    1060             pig  / baz horse owl | 
    1061             keg  / cat horse+ owl? baz | 
    1062             pig  / cat* cat cat | 
    1063             beer / twin * car; 
    1064         twin : 
    1065             beer / king qween* ; 
    1066         car : 
    1067             keg / king qween qween king; 
    1068             "; 
    1069  
    1070     pragma(msg, ReduceWhite(gram)); 
    1071  
    1072     mixin Parser!("root",ReduceWhite(gram)); 
    1073 
    1074  
    1075 class data : IParser 
    1076 
    1077     char[] dat; 
    1078     uint i =0; 
    1079     uint pos()      {return i;} 
    1080     void pos(uint j){ i = j;} 
    1081 
     1092debug(dparse_unittest) 
     1093
     1094    // Unittest code 
     1095    unittest 
     1096    { 
     1097        writef("unittest@"__FILE__":"~itoa!(__LINE__)~\n); 
     1098 
     1099        P p; 
     1100        data d = new data; 
     1101        char[][] pass = 
     1102            [ 
     1103            "BB"[],         //root > next baz > (baz) baz) 
     1104            "HOB",          //root > next baz > (owl* horse owl) baz > (() horse owl) baz 
     1105            "OHOB",         //root > next baz > (owl* horse owl) baz > ((owl) horse owl) baz 
     1106            "OOHOB",        //root > next baz > (owl* horse owl) baz > ((owl owl) horse owl) baz 
     1107            "BHO",          //root > baz horse owl 
     1108            "CHB",          //root > cat horse+ owl* baz > cat (horse) () baz 
     1109            "CHOB",         //root > cat horse+ owl* baz > cat (horse) (owl) baz 
     1110            "CHHOB",        //root >  cat horse+ owl* baz > cat (horse horse) (owl) baz 
     1111            "CCC",          //root > cat* cat cat > (cat) cat cat 
     1112            "KQKQKQKQQKQK", // root > twin* car > (twin twin twin) (car) > ((king qween) (king qween) (king qween)) (king qween qween king) 
     1113            ], 
     1114            fail = 
     1115            [ 
     1116            "BHHO"[], 
     1117            "COB", 
     1118            "CB", 
     1119            "CHHOOB", 
     1120            ]; 
     1121     
     1122        foreach(char[] passTest; pass) 
     1123        { 
     1124            d.dat = passTest; 
     1125            d.i=0; 
     1126            assert(!p.Parser(d).fail, \"~passTest~"\" failed to parse"); 
     1127        } 
     1128     
     1129        foreach(char[] failTest; fail) 
     1130        { 
     1131            d.dat = failTest; 
     1132            d.i=0; 
     1133             assert(p.Parser(d).fail, \"~failTest~"\" failed to fail to parse"); 
     1134        } 
     1135    } 
     1136     
     1137    struct P 
     1138    { 
     1139        PObject Terminal(char[] str : "baz")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'B') return new PObjectFail; d.i++; return new PObjectBox!(char)('B');} 
     1140        PObject Terminal(char[] str : "owl")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'O') return new PObjectFail; d.i++; return new PObjectBox!(char)('O');} 
     1141        PObject Terminal(char[] str : "horse")(IParser i) {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'H') return new PObjectFail; d.i++; return new PObjectBox!(char)('H');} 
     1142        PObject Terminal(char[] str : "cat")(IParser i)   {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'C') return new PObjectFail; d.i++; return new PObjectBox!(char)('C');} 
     1143        PObject Terminal(char[] str : "king")(IParser i)  {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'K') return new PObjectFail; d.i++; return new PObjectBox!(char)('K');} 
     1144        PObject Terminal(char[] str : "qween")(IParser i) {data d = cast(data)i; if(d.i >= d.dat.length || d.dat[d.i] != 'Q') return new PObjectFail; d.i++; return new PObjectBox!(char)('Q');} 
     1145     
     1146        PObject Action(char[] str : "bar") (PObject[1] i){return new PObjectVector!(1)(i);} 
     1147        PObject Action(char[] str : "beer")(PObject[2] i){return new PObjectVector!(2)(i);} 
     1148        PObject Action(char[] str : "pig") (PObject[3] i){return new PObjectVector!(3)(i);} 
     1149        PObject Action(char[] str : "keg") (PObject[4] i){return new PObjectVector!(4)(i);} 
     1150     
     1151        const char[] gram = " 
     1152            next : 
     1153                bar / baz | 
     1154                pig / owl * horse owl ; 
     1155            root : 
     1156                beer / next baz | 
     1157                pig  / baz horse owl | 
     1158                keg  / cat horse+ owl? baz | 
     1159                pig  / cat* cat cat | 
     1160                beer / twin * car; 
     1161            twin : 
     1162                beer / king qween* ; 
     1163            car : 
     1164                keg / king qween qween king; 
     1165                "; 
     1166     
     1167        debug(dparse_verbose) pragma(msg, ReduceWhite(gram)); 
     1168     
     1169        mixin Parser!("root",ReduceWhite(gram)); 
     1170    } 
     1171 
     1172    class data : IParser 
     1173    { 
     1174        char[] dat; 
     1175        uint i =0; 
     1176        uint pos()      {return i;} 
     1177        void pos(uint j){ i = j;} 
     1178    } 
     1179