Changeset 15

Show
Ignore:
Timestamp:
02/04/07 23:20:47 (5 years ago)
Author:
BCS
Message:

added +, ? and *

Files:

Legend:

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

    r5 r15  
    154154} 
    155155 
     156template DropID(char[] string) 
     157{ 
     158    const char[] DropID = string[GetID!(string).length .. $]; 
     159} 
     160 
     161 
    156162/*********** 
    157163    return tuple with string  broken up by d 
     
    216222    bool fail; 
    217223    this(){fail = true;} 
     224} 
     225 
     226 
     227class PObjectSet : PObject 
     228{ 
     229    PObject[] set; 
     230    this(){ set = null; } 
     231 
     232    uint Add(PObject o) 
     233    { 
     234        uint ret = set.length; 
     235        set ~= o; 
     236        fail = false; 
     237        return ret; 
     238    } 
     239 
     240    void Back(uint b) 
     241    { 
     242        set.length = b; 
     243    } 
    218244} 
    219245 
     
    246272 
    247273        debug writef("Try\t(%d)%s...\n", ind, ruleIs); 
    248         debug scope(exit) writef("Done\t(%d)%s %s\n", ind, ruleIs, worked); 
     274        debug scope(success) writef("Done\t(%d)%s %s\n", ind, ruleIs, worked); 
     275        debug scope(failure) writef("FAILED\t(%d)%s %s\n", ind, ruleIs, worked); 
    249276 
    250277        pragma(msg, "Seeking: "~ruleIs); 
     278 
     279        struct Frame{uint pos; uint rule; uint count;} 
     280        Stack!(Frame) backups; 
     281        Frame store; 
     282 
    251283        foreach(int i, char[] str; V) 
    252284        { 
     
    267299                    debug writef("*\t(%d)%s:%s...\n", ind, ruleIs,DiscardTill!(Case,'/')); 
    268300 
     301                    backups.Empty(); 
     302                    store.rule = -1;    // init case 
     303 
    269304                        // return to start location 
    270305                    p.pos = start; 
     
    274309                    const int count = clauses.length; 
    275310                    PObject[count] temps; 
    276                         // try clauses 
    277                     foreach(index, cl;clauses) 
     311                    PObject tmpStore; 
     312 
     313                    do 
    278314                    { 
    279                         const char[] clause = clauses[index]; 
    280                         pragma(msg, "clauseLoop: "~clause); 
    281                             // parse item 
    282                         temps[index] = Rule!(GetID!(clause))(p); 
    283                             // if failed try next case 
    284                         if(temps[index].fail) 
    285                             continue caseLoop; 
    286                             // otherwise try next clause 
    287                     } 
    288                         // enact reduction when all clauses fit. 
    289                     pragma(msg,"Action: \""~GetID!(UseTill!(Case,'/'))~\"); 
    290                     debug worked = true; 
    291                     debug writef(">\t(%d)%s\n", ind, GetID!(UseTill!(Case,'/'))); 
    292                     auto ret = Action!(GetID!(UseTill!(Case,'/')))(temps); 
    293                     return ret; 
     315                        switch(store.rule) 
     316                        { 
     317                            case -1: 
     318                                // try clauses 
     319                            foreach(index, cl;clauses) 
     320                            { 
     321                                    // static stuff 
     322 
     323                                const char[] clause = clauses[index]; 
     324                                debug writef("Attemping clause %s...\n", clause); 
     325 
     326                                pragma(msg, "clauseLoop: "~clause); 
     327                                const char sufix = (DropID!(clause) ~ " ")[0]; 
     328                                pragma(msg, "Sufix is: \""~DropID!(clause)~\"); 
     329 
     330                                    // on */+/? add a set 
     331                                static if(sufix == '*' || sufix == '+' || sufix == '?') 
     332                                    temps[index] = new PObjectSet(); 
     333                                    // label clause 
     334 
     335                                case index: 
     336 
     337                                store.pos = p.pos; 
     338                                store.rule = index; 
     339 
     340                                uint pre = p.pos; 
     341 
     342                                    // parse item 
     343                                tmpStore = Rule!(GetID!(clause))(p); 
     344                                assert(tmpStore !is null); 
     345 
     346                                    // if failed try next case 
     347                                static if(sufix == '?') 
     348                                {   // optional, non-repeating 
     349                                    if(tmpStore.fail) 
     350                                    { 
     351                                        debug writef("clause %s failed, skipping clause\n", clause); 
     352                                        // failure OK 
     353                                        p.pos = pre; 
     354                                    } 
     355                                    else  
     356                                    { 
     357                                        debug writef("clause %s passed, including clause\n", clause); 
     358                                        with(cast(PObjectSet)temps[index]) 
     359                                        { 
     360                                            store.count = set.length; 
     361                                            Add(tmpStore); 
     362                                        } 
     363                                        backups.Push(store); 
     364                                    } 
     365                                } 
     366                                else static if(sufix == '*') 
     367                                {   // optional, repeating 
     368                                    if(tmpStore.fail) 
     369                                    { 
     370                                        debug writef("clause %s failed continuing with next clause\n", clause); 
     371                                        // failure OK 
     372                                        p.pos = pre; 
     373                                    } 
     374                                    else  
     375                                    { 
     376                                        debug writef("clause %s passed re trying clause\n", clause); 
     377                                        with(cast(PObjectSet)temps[index]) 
     378                                        { 
     379                                            store.count = set.length; 
     380                                            Add(tmpStore); 
     381                                        } 
     382                                        backups.Push(store); 
     383                                        goto case index; // try for anther 
     384                                    } 
     385                                } 
     386                                else static if(sufix == '+') 
     387                                {   // required, repeating 
     388                                    if(tmpStore.fail) 
     389                                    { 
     390                                        if((cast(PObjectSet)temps[index]).set is null) 
     391                                        { 
     392                                            // falure befor parse invalid 
     393                                            debug writef("clause %s failed befor success\n", clause); 
     394                                            goto case -2; 
     395                                        } 
     396                                        debug writef("clause %s failed after success\n", clause); 
     397                                        // otherwise failure OK 
     398                                        p.pos = pre; 
     399                                    } 
     400                                    else  
     401                                    { 
     402                                        auto set_t = cast(PObjectSet)temps[index]; 
     403                                        if((cast(PObjectSet)temps[index]).set !is null) 
     404                                        { 
     405                                            debug writef("clause %s passed  again re trying clause\n", clause); 
     406                                            store.count = set_t.set.length; 
     407                                            backups.Push(store); 
     408                                        } 
     409                                        else 
     410                                        { 
     411                                            debug writef("clause %s passed once, re trying clause\n", clause); 
     412                                        } 
     413 
     414                                        set_t.Add(tmpStore); 
     415                                        goto case index; // try for anther 
     416                                    } 
     417                                } 
     418                                else    // required 
     419                                { 
     420                                    if(tmpStore.fail) 
     421                                    { 
     422                                        debug writef("clause %s failed\n", clause); 
     423                                        goto case -2; 
     424                                    } 
     425                                    temps[index] = tmpStore; 
     426                                    debug writef("clause %s passed trying next clause\n", clause); 
     427                                } 
     428 
     429                                // fall throught to next case 
     430                            } 
     431                                // enact reduction when all clauses fit. 
     432                            pragma(msg,"Action: \""~GetID!(UseTill!(Case,'/'))~\"); 
     433                            debug worked = true; 
     434                            debug writef("run\t(%d)%s\n", ind, GetID!(UseTill!(Case,'/'))); 
     435 
     436                            auto ret = Action!(GetID!(UseTill!(Case,'/')))(temps); 
     437                            assert(ret !is null); 
     438                            return ret; 
     439 
     440 
     441                            case -2:    // backup and retry 
     442 
     443                                // can we backup? 
     444                            if(backups.Count <= 0) 
     445                            { 
     446                                // no, fail disjunction 
     447                                debug writef("clause failed, out of opinions, trying next disjunction\n"); 
     448                                continue caseLoop; 
     449                            } 
     450 
     451                            store = backups.Pop; 
     452                            store.rule++; 
     453                            p.pos = store.pos; 
     454 
     455                            debug writef("clause failed backing up to %d with clause %d\n", store.pos, store.rule); 
     456                        } 
     457                    }while(true); 
     458 
    294459                } 
    295460 
     
    305470            debug writef("T\t(%d)%s...\n", ind, ruleIs); 
    306471            auto ret = Terminal!(ruleIs)(p); 
     472            assert(ret !is null); 
    307473            debug worked = !ret.fail; 
    308474            return ret; 
     
    312478    alias Rule!(start) Parser; 
    313479} 
     480 
     481unittest 
     482{ 
     483    Stack!(int) st; 
     484    int i; 
     485    for(i = 0; i < 20; i++) 
     486    { 
     487        assert(st.Count == i); 
     488        st.Push(i); 
     489    } 
     490 
     491    i--; 
     492 
     493    for(; i >= 0; i--) 
     494    { 
     495        int j = st.Pop; 
     496        assert(j == i); 
     497        assert(st.Count == i); 
     498    } 
     499 
     500    assert(st.Count == 0); 
     501 
     502 
     503} 
     504 
     505struct Stack(T) 
     506{ 
     507    private T[] data = null; 
     508    private int at = 0; 
     509 
     510    void Push(T din) 
     511    { 
     512        if(data.length <= at) 
     513            data.length = data.length + 10; 
     514        data[at] = din; 
     515        at++; 
     516    } 
     517 
     518    T Pop() 
     519    { 
     520        if(at) 
     521        { 
     522            at--; 
     523            return data[at]; 
     524        } 
     525        else 
     526            throw new Error("Stack Underflow"); 
     527    } 
     528 
     529    uint Count(){return at;} 
     530 
     531    void Empty(){ at = 0; } 
     532 
     533    void Dist(){delete data;} 
     534}