root/trunk/orca/parse.c

Revision 156, 30.3 kB (checked in by krobillard, 2 years ago)

Orca - Ported parse from Thune.

Line 
1/*============================================================================
2    ORCA Interpreter
3    Copyright (C) 2005-2006  Karl Robillard
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18===========================================================================*/
19
20
21#include "os.h"
22#include "ovalue.h"
23#include "orca_atoms.h"
24#include "internal.h"
25
26
27#define PARSE_EX
28#define orChar          orInt
29#define UChar           char
30#define OR_ITER_BLOCK(ita,itb,blk,scell) \
31    ita = blk->values + scell->series.it; \
32    itb = blk->values + blk->used;
33
34
35
36extern int orMatchString( const OString* strA, int iA,
37                          const OString* strB, int iB );
38extern int orFindString( const OString* strA, int iA,
39                         const OString* strB, int iB );
40
41
42typedef struct
43{
44    uint8_t  type;
45    uint8_t  flags;
46    uint8_t  datatype;
47    uint8_t  _pad;
48    OIndex  n;      /* Series number */
49    OIndex  it;     /* Element Iterator */
50    OIndex  end;    /* Slice end */
51}
52UCellSlice;
53
54
55typedef struct
56{
57    //UThread*   thread;
58    OValue*    rules;
59    UCellSlice input;
60    OString*   str;
61    int        error;
62    int        matchCase;
63}
64StringParser;
65
66
67typedef struct
68{
69    //UThread*   thread;
70    OValue*     rules;
71    UCellSlice  input;
72    OString*   blk;
73    int        error;
74}
75BlockParser;
76
77
78/*
79  Goto next rule; search for '|'.
80*/
81static const OValue* nextRule( const OValue* it, const OValue* end )
82{
83    while( it != end )
84    {
85        if( orIs(it, OT_WORD) && (orAtom(it) == OR_ATOM_BAR) )
86        {
87            return it + 1;
88        }
89        ++it;
90    }
91    return 0;
92}
93
94
95static int _repeatChar( OString* input, OIndex pos, int limit, int c )
96{
97    UChar* start;
98    UChar* it;
99    UChar* end;
100
101    it  = input->charArray;
102    end = it + input->used;
103    it += pos;
104    if( end > (it + limit) )
105        end = it + limit;
106
107    start = it;
108    while( it != end )
109    {
110        if( *it != c )
111            break;
112        ++it;
113    }
114    return it - start;
115}
116
117
118static int _repeatBitset( OString* input, OIndex pos, int limit,
119                          const OValue* patc )
120{
121    UChar* start;
122    UChar* it;
123    UChar* end;
124    int c;
125    OBinary* bin = orSTRING(patc);
126    const uint8_t* bits = bin->byteArray;
127    int maxC = bin->used * 8;
128
129    it  = input->charArray;
130    end = it + input->used;
131    it += pos;
132    if( end > (it + limit) )
133        end = it + limit;
134
135    start = it;
136    while( it != end )
137    {
138        c = *it;
139        if( c >= maxC )
140            break;
141        if( ! orBitIsSet( bits, c ) )
142            break;
143        ++it;
144    }
145    return it - start;
146}
147
148
149/*
150   Returns zero if matching rule not found.
151*/
152static const OValue* _parseStr( StringParser* pe, const OValue* rit,
153                               const OValue* rend, OIndex* spos )
154{
155    const OBlock* cblk;
156    const OValue* tval;
157    int32_t repMin;
158    int32_t repMax;
159    OString* istr;
160    OIndex pos = *spos;
161
162    istr = pe->str;
163
164match:
165
166    while( rit != rend )
167    {
168        switch( orType(rit) )
169        {
170            case OT_WORD:
171                switch( orAtom(rit) )
172                {
173                case OR_ATOM_OPT:
174                    ++rit;
175                    repMin = 0;
176                    repMax = 1;
177                    goto repeat;
178
179                case OR_ATOM_ANY:
180                    ++rit;
181                    repMin = 0;
182                    repMax = 0x7fffffff;
183                    goto repeat;
184
185                case OR_ATOM_SOME:
186                    ++rit;
187                    repMin = 1;
188                    repMax = 0x7fffffff;
189                    goto repeat;
190
191                case OR_ATOM_BREAK:
192                    return rit;
193
194                case OR_ATOM_BAR:
195                    goto complete;
196
197                case OR_ATOM_TO:
198                case OR_ATOM_THRU:
199                {
200                    OAtom ratom = orAtom(rit);
201
202                    ++rit;
203                    if( rit == rend )
204                        return 0;
205
206                    if( orIs(rit, OT_WORD) )
207                    {
208                        orWordVal( rit, cblk, tval );
209                    }
210                    else
211                    {
212                        tval = rit;
213                    }
214
215                    switch( orType(tval) )
216                    {
217                        case OT_CHAR:
218                        {
219                            int c = orChar(tval);
220                            UChar* cp  = istr->charArray + pos;
221                            UChar* end = istr->charArray + pe->input.end;
222                            while( cp != end )
223                            {
224                                if( *cp == c )
225                                    break;
226                                ++cp;
227                            }
228                            if( cp == end )
229                                goto failed;
230                            pos = cp - istr->charArray;
231                            if( ratom == OR_ATOM_THRU )
232                                ++pos;
233                        }
234                            break;
235
236                        case OT_STRING:
237                        {
238                            OString* pat = orSTRING(tval);
239                            pos = orFindString( istr, pos,
240                                                pat, tval->series.it );
241                            if( pos < 0 )
242                                goto failed;
243                            if( ratom == OR_ATOM_THRU )
244                                pos += pat->used - tval->series.it;
245                        }
246                            break;
247
248                        case OT_BITSET:
249                        {
250                            OBinary* bin = orSTRING(tval);
251                            const uint8_t* bits = bin->byteArray;
252                            int maxC = bin->used * 8;
253                            UChar* cp  = istr->charArray + pos;
254                            UChar* end = istr->charArray + pe->input.end;
255                            int c;
256                            while( cp != end )
257                            {
258                                c = *cp;
259                                if( c < maxC )
260                                {
261                                    if( orBitIsSet( bits, c ) )
262                                        break;
263                                }
264                                ++cp;
265                            }
266                            if( cp == end )
267                                goto failed;
268                            pos = cp - istr->charArray;
269                            if( ratom == OR_ATOM_THRU )
270                                ++pos;
271                        }
272                            break;
273
274                        case OT_BLOCK:
275                            // TODO
276                            orError( PARSE_EX
277                                     "to/thru block! not implemented" );
278                            pe->error = 1;
279                            return 0;
280                    }
281                    ++rit;
282                }
283                    break;
284
285                case OR_ATOM_SKIP:
286                    // TODO - int! skip
287                    //if( pos >= istr->used )
288                    //    return 0;
289                    ++rit;
290                    ++pos;
291                    break;
292
293                //case OR_ATOM_COPY:
294
295                default:
296                    orWordVal( rit, cblk, tval );
297
298                    if( orIs(tval, OT_CHAR) )
299                        goto match_char;
300                    else if( orIs(tval, OT_STRING) )
301                        goto match_string;
302                    else if( orIs(tval, OT_BLOCK) )
303                        goto match_block;
304                    else if( orIs(tval, OT_BITSET) )
305                        goto match_bitset;
306                    else
307                    {
308                        orError( PARSE_EX
309                                 "parse expected char!/block!/bitset!" );
310                        pe->error = 1;
311                        return 0;
312                    }
313                    break;
314                }
315                break;
316
317            case OT_SETWORD:
318            {
319                OValue* cell;
320                orWordVal( rit, cblk, cell );
321                ++rit;
322
323                orSetTF( cell, OT_STRING );
324                orSetSeries( cell, pe->input.n, pos );
325            }
326                break;
327#if 0
328            case OT_GETWORD:
329            {
330                OValue* cell;
331                orWordVal( rit, cblk, cell );
332                ++rit;
333
334                if( orIs(cell, OT_SLICE) && (cell->series.n == pe->input.n) )
335                    cell->slice.end = pos;
336            }
337                break;
338#endif
339            case OT_INTEGER:
340                repMin = orInt(rit);
341
342                ++rit;
343                if( rit == rend )
344                    return 0;
345
346                if( orIs(rit, OT_INTEGER) )
347                {
348                    repMax = orInt(rit);
349                    ++rit;
350                }
351                else
352                {
353                    repMax = repMin;
354                }
355                goto repeat;
356
357            case OT_CHAR:
358                tval = rit;
359match_char:
360                if( istr->charArray[ pos ] == orChar(tval) )
361                {
362                    ++rit;
363                    ++pos;
364                }
365                else
366                    goto failed;
367                break;
368
369            case OT_BLOCK:
370                tval = rit;
371match_block:
372                cblk = orBLOCK( tval );
373                tval = _parseStr( pe, cblk->values + tval->series.it,
374                                      cblk->values + cblk->used, &pos );
375                istr = pe->str;
376                if( ! tval )
377                    goto failed_eval;
378                ++rit;
379                break;
380
381            case OT_PAREN:
382                orEvalBlock( orBlockPtr(rit->series.n), rit->series.it );
383                if( orErrorThrown )
384                {
385                    pe->error = 1;
386                    return 0;
387                }
388
389                /* Re-aquire pointer & check if input modified. */
390                istr = pe->str = orStringPtr( pe->input.n );
391                if( istr->used < pe->input.end )
392                    pe->input.end = istr->used;
393
394                ++rit;
395                break;
396
397            case OT_STRING:
398                tval = rit;
399match_string:
400            {
401                OString* pat = orSTRING( tval );
402
403                /*
404                if( pe->matchCase )
405                    pos = orMatchStringCase(istr, pos, pat, tval->series.it);
406                else
407                */
408                    pos = orMatchString( istr, pos, pat, tval->series.it );
409
410                if( pos )
411                    ++rit;
412                else
413                    goto failed;
414            }
415                break;
416
417            case OT_BITSET:
418                tval = rit;
419match_bitset:
420            {
421                OString* bin = orSTRING( tval );
422                int c;
423
424                c = istr->charArray[ pos ];
425                if( orBitIsSet( bin->byteArray, c ) )
426                {
427                    ++rit;
428                    ++pos;
429                }
430                else
431                    goto failed;
432            }
433                break;
434
435            default:
436                orError( PARSE_EX "invalid parse value" );
437                             //orDatatypeName( orType(rit) ) );
438                pe->error = 1;
439                return 0;
440        }
441    }
442
443complete:
444
445    *spos = pos;
446    return rit;
447
448repeat:
449
450    /* Repeat rit for repMin to repMax times. */
451
452    if( rit == rend )
453    {
454        orError( PARSE_EX "Enexpected end of parse rule" );
455        pe->error = 1;
456        return 0;
457    }
458    else
459    {
460        int count;
461
462        if( orIs(rit, OT_WORD) )
463        {
464            orWordVal( rit, cblk, tval );
465        }
466        else
467        {
468            tval = rit;
469        }
470
471        switch( orType(tval) )
472        {
473            case OT_CHAR:
474                count = _repeatChar( istr, pos, repMax, orChar(tval) );
475                pos += count;
476                break;
477
478            case OT_STRING:
479            {
480                OString* pat;
481                int p2;
482
483                count = 0;
484                pat = orSTRING(tval);
485
486                while( count < repMax )
487                {
488                    p2 = orMatchString( istr, pos, pat, tval->series.it );
489                    if( ! p2 )
490                        break;
491                    pos = p2;
492                    ++count;
493                }
494            }
495                break;
496
497            case OT_BITSET:
498                count = _repeatBitset( istr, pos, repMax, tval );
499                pos += count;
500                break;
501
502            case OT_BLOCK:
503            {
504                OValue* ci;
505                OValue* ce;
506
507                count = 0;
508                cblk = orBLOCK( tval );
509                OR_ITER_BLOCK( ci, ce, cblk, tval );
510
511                while( count < repMax )
512                {
513                    if( pos == pe->input.end )
514                        break;
515                    if( ! _parseStr( pe, ci, ce, &pos ) )
516                        break;
517                    ++count;
518                }
519                if( pe->error )
520                    return 0;
521                istr = pe->str;
522            }
523                break;
524
525            default:
526                orError( PARSE_EX "Invalid parse rule" );
527                pe->error = 1;
528                return 0;
529        }
530
531        if( count < repMin )
532            goto failed;
533        ++rit;
534    }
535    goto match;
536
537failed_eval:
538
539    if( pe->error )
540        return 0;
541
542failed:
543
544    rit = nextRule( rit, rend );
545    if( rit )
546    {
547        pos = *spos;
548        goto match;
549    }
550    return 0;
551}
552
553
554#if 0
555static const char* _parseStrFailedMessage( StringParser* pe,
556                                           const UChar* it, const UChar* end )
557{
558    UChar* dest;
559    OString* str = orStringPtr( pe->thread->callTempBinN );
560    str->used = 0;
561    ur_strCat( str, "parse failed at \"", 17 );
562
563    orArrayReserve( str, sizeof(UChar), str->used + (end - it) + 2 );
564    dest = str->charArray + str->used;
565    while( it != end )
566    {
567        if( *it == '\n' )
568            break;
569        *dest++ = *it++;
570        //++str->used;
571    }
572    *dest++ = '"';
573    *dest   = '\0';
574
575    return str->charArray;
576}
577#endif
578
579
580static void _parseStringS( OValue* a1, OValue* rules, int all, int useCase )
581{
582    OBinary* custom;
583    uint8_t* delim;
584    const char* cp;
585    const char* end;
586    const char* sstart;
587    OBlock* rblk;
588    OIndex rblkN;
589    OIndex rblkHold;
590    OIndex customHold;
591    OString* str = orSTRING(a1);
592
593    (void) useCase;
594
595    rblk  = orMakeBlock( 0 );
596    rblkN = orBlockN( rblk );
597    rblkHold = orHold( OT_BLOCK, rblkN );
598
599    if( orIs(rules, OT_STRING) )
600    {
601        custom = orMakeCharset( orSTRING(rules), rules->series.it );
602        customHold = orHold( OT_BINARY, orStringN(custom) );
603        delim = custom->byteArray;
604        if( ! all )
605        {
606            cp = "\t\n\r ,;";
607            while( *cp )
608            {
609                orSetBit( delim, *cp );
610                ++cp;
611            }
612        }
613    }
614    else
615    {
616        custom = 0;
617        delim = (uint8_t*) memAlloc(32);
618        memCpy( delim, charset_white, 32 );
619        orSetBit( delim, ',' );
620        orSetBit( delim, ';' );
621    }
622
623
624    assert( a1->series.it <= str->used );
625
626    cp  = str->charArray + a1->series.it;
627    end = str->charArray + str->used;
628    sstart = cp;
629
630    while( cp != end )
631    {
632        int c = *cp;
633        if( orBitIsSet(delim, c) )
634        {
635            if( cp > sstart )
636            {
637                orAppendString( rblk, orMakeCString(sstart, cp-sstart) );
638            }
639            sstart = cp + 1;
640        }
641        ++cp;
642    }
643
644    if( cp > sstart )
645    {
646        orAppendString( rblk, orMakeCString(sstart, cp-sstart) );
647    }
648
649    if( custom )
650    {
651        orRelease( customHold );
652        orArrayFree( custom );  // Garbage collection will free this later.
653    }
654    else
655    {
656        memFree( delim );
657    }
658
659    orRelease( rblkHold );
660    orResultBLOCK( rblkN );
661}
662
663
664/*==========================================================================*/
665
666
667#if 0
668/**
669  Returns index in blk where fval is found or -1 if fval is not found.
670*/
671static int _findBlock( const OBlock* blk, OIndex pos, const OValue* fval )
672{
673    const OValue* it  = blk->values + pos;
674    const OValue* end = blk->values + blk->used;
675
676    // TODO: If fval is block then all values must match.
677
678    assert( pos <= blk->used );
679
680    while( it != end )
681    {
682        if( ur_equal(it, fval) )
683            return it - blk->values;
684        ++it;
685    }
686    return -1;
687}
688#endif
689
690
691/*
692   Returns zero if matching rule not found.
693*/
694static const OValue* _parseBlock( BlockParser* pe, const OValue* rit,
695                                 const OValue* rend, int* spos )
696{
697    const OBlock* cblk;
698    const OValue* tval;
699    int32_t repMin;
700    int32_t repMax;
701    OAtom atom;
702    OBlock* iblk;
703    OIndex pos = *spos;
704
705    iblk = pe->blk;
706
707match:
708
709    while( rit != rend )
710    {
711        switch( orType(rit) )
712        {
713            case OT_WORD:
714                atom = orAtom(rit);
715
716                if( atom < OT_COUNT )
717                {
718                    // Datatype
719                    if( pos >= pe->input.end )
720                        goto failed;
721                    tval = iblk->values + pos;
722                    if( orType(tval) != atom )
723                    {
724                        if( atom == OT_NUMBER )
725                        {
726                            if( orIs(tval,OT_INTEGER) || orIs(tval,OT_DECIMAL) )
727                                goto type_matched;
728                        }
729                        goto failed;
730                    }
731type_matched:
732                    ++rit;
733                    ++pos;
734                }
735                else switch( atom )
736                {
737                    case OR_ATOM_OPT:
738                        ++rit;
739                        repMin = 0;
740                        repMax = 1;
741                        goto repeat;
742
743                    case OR_ATOM_ANY:
744                        ++rit;
745                        repMin = 0;
746                        repMax = 0x7fffffff;
747                        goto repeat;
748
749                    case OR_ATOM_SOME:
750                        ++rit;
751                        repMin = 1;
752                        repMax = 0x7fffffff;
753                        goto repeat;
754
755                    case OR_ATOM_BREAK:
756                        return rit;
757
758                    case OR_ATOM_BAR:
759                        goto complete;
760
761                    case OR_ATOM_TO:
762                    case OR_ATOM_THRU:
763                    {
764                        const OValue* ci;
765                        const OValue* ce;
766                        OAtom ratom = orAtom(rit);
767
768                        ++rit;
769                        if( rit == rend )
770                            return 0;
771
772                        ci = iblk->values + pos;
773                        ce = iblk->values + pe->input.end;
774
775                        if( orIs(rit, OT_WORD) )
776                        {
777                            if( orAtom(rit) < OT_COUNT )
778                            {
779                                atom = orAtom(rit);
780                                while( ci != ce )
781                                {
782                                    if( orType(ci) == atom )
783                                        break;
784                                    ++ci;
785                                }
786                                if( ci == ce )
787                                    goto failed;
788                                pos = ci - iblk->values;
789                                if( ratom == OR_ATOM_THRU )
790                                    ++pos;
791                                ++rit;
792                                break;
793                            }
794                            else
795                            {
796                                orWordVal( rit, cblk, tval );
797                            }
798                        }
799                        else
800                        {
801                            tval = rit;
802                        }
803
804
805                        if( orIs(tval, OT_BLOCK) )
806                        {
807                            // TODO: If block then all values must match.
808                            orError( PARSE_EX
809                                     "to/thru block! not implemented" );
810                            pe->error = 1;
811                            return 0;
812                        }
813                        else
814                        {
815                            while( ci != ce )
816                            {
817                                if( orEqual(ci, tval) )
818                                    break;
819                                ++ci;
820                            }
821                            if( ci == ce )
822                                goto failed;
823                            pos = ci - iblk->values;
824                            if( ratom == OR_ATOM_THRU )
825                                ++pos;
826                        }
827                        ++rit;
828                    }
829                        break;
830
831                    case OR_ATOM_SKIP:
832                        // TODO - int! skip
833                        //if( pos >= ser->used )
834                        //    return 0;
835                        ++rit;
836                        ++pos;
837                        break;
838
839                    //case OR_ATOM_COPY:
840
841                    default:
842                    {
843                        orWordVal( rit, cblk, tval );
844
845                        if( orIs(tval, OT_BLOCK) )
846                        {
847                            goto match_block;
848                        }
849                        else
850                        {
851                            orError( PARSE_EX "parse expected block" );
852                            pe->error = 1;
853                            return 0;
854                        }
855                    }
856                        break;
857                }
858                break;
859
860            case OT_SETWORD:
861            {
862                OValue* cell;
863                orWordVal( rit, cblk, cell );
864                ++rit;
865
866                orSetTF( cell, OT_BLOCK );
867                orSetSeries( cell, pe->input.n, pos );
868            }
869                break;
870#if 0
871            case OT_GETWORD:
872            {
873                OValue* cell;
874                orWordVal( rit, cblk, cell );
875                ++rit;
876
877                if( orIs(cell, OT_SLICE) && (cell->series.n == pe->input.n) )
878                    cell->slice.end = pos;
879            }
880                break;
881#endif
882            case OT_LITWORD:
883                if( pos >= pe->input.end )
884                    goto failed;
885                tval = iblk->values + pos;
886                if( orIs(tval, OT_WORD) && (orAtom(tval) == orAtom(rit)) )
887                {
888                    ++rit;
889                    ++pos;
890                }
891                else
892                    goto failed;
893                break;
894
895            case OT_INTEGER:
896                repMin = orInt(rit);
897
898                ++rit;
899                if( rit == rend )
900                    return 0;
901
902                if( orIs(rit, OT_INTEGER) )
903                {
904                    repMax = orInt(rit);
905                    ++rit;
906                }
907                else
908                {
909                    repMax = repMin;
910                }
911                goto repeat;
912#if 0
913            case OT_DATATYPE:
914            {
915                OValue* val;
916
917                blk = orBlockPtr(blkN);
918                val = blk->values + pos;
919                if( orType(val) == ur_datatype(rit) )
920                {
921                    ++rit;
922                    ++pos;
923                }
924                else
925                    goto failed;
926            }
927                break;
928#endif
929            case OT_BLOCK:
930                tval = rit;
931match_block:
932                cblk = orBLOCK( tval );
933                tval = _parseBlock( pe, cblk->values + tval->series.it,
934                                        cblk->values + cblk->used, &pos );
935                iblk = pe->blk;
936                if( ! tval )
937                    goto failed_eval;
938                ++rit;
939                break;
940
941            case OT_PAREN:
942                orEvalBlock( orBlockPtr(rit->series.n), rit->series.it );
943                if( orErrorThrown )
944                {
945                    pe->error = 1;
946                    return 0;
947                }
948
949                /* Re-aquire pointer & check if input modified. */
950                iblk = pe->blk = orBlockPtr( pe->input.n );
951                if( iblk->used < pe->input.end )
952                    pe->input.end = iblk->used;
953
954                ++rit;
955                break;
956
957            default:
958                orError( PARSE_EX "invalid parse value" );
959                pe->error = 1;
960                return 0;
961        }
962    }
963
964complete:
965
966    *spos = pos;
967    return rit;
968
969repeat:
970
971    /* Repeat rit for repMin to repMax times. */
972
973    if( rit == rend )
974    {
975        orError( PARSE_EX "Enexpected end of parse rule" );
976        pe->error = 1;
977        return 0;
978    }
979    else
980    {
981        int count;
982
983        if( orIs(rit, OT_WORD) )
984        {
985            orWordVal( rit, cblk, tval );
986        }
987        else
988        {
989            tval = rit;
990        }
991
992        switch( orType(tval) )
993        {
994            case OT_DATATYPE:
995                // If repMax would pass end of input limit repMax.
996                count = pe->input.end - pos;
997                if( count < repMax )
998                    repMax = count;
999                count = 0;
1000
1001                atom = orDatatype(tval);
1002                while( count < repMax )
1003                {
1004                    tval = iblk->values + pos;
1005                    if( orType(tval) != atom )     // Test mask?
1006                        break;
1007                    ++pos;
1008                    ++count;
1009                }
1010                break;
1011
1012            case OT_LITWORD:
1013                // If repMax would pass end of input limit repMax.
1014                count = pe->input.end - pos;
1015                if( count < repMax )
1016                    repMax = count;
1017                count = 0;
1018
1019                atom = orAtom(tval);
1020                while( count < repMax )
1021                {
1022                    tval = iblk->values + pos;
1023                    if( ! orIs(tval, OT_WORD) )
1024                        break;
1025                    if( orAtom(tval) != atom )
1026                        break;
1027                    ++pos;
1028                    ++count;
1029                }
1030                break;
1031
1032            case OT_BLOCK:
1033            {
1034                const OValue* ci;
1035                const OValue* ce;
1036
1037                count = 0;
1038                cblk = orBLOCK( tval );
1039                OR_ITER_BLOCK( ci, ce, cblk, tval );
1040
1041                while( count < repMax )
1042                {
1043                    if( pos == pe->input.end )
1044                        break;
1045                    if( ! _parseBlock( pe, ci, ce, &pos ) )
1046                        break;
1047                    ++count;
1048                }
1049                if( pe->error )
1050                    return 0;
1051                iblk = pe->blk;
1052            }
1053                break;
1054
1055            default:
1056                orError( PARSE_EX "Invalid parse rule" );
1057                pe->error = 1;
1058                return 0;
1059        }
1060
1061        if( count < repMin )
1062            goto failed;
1063        ++rit;
1064    }
1065    goto match;
1066
1067failed_eval:
1068
1069    if( pe->error )
1070        return 0;
1071
1072failed:
1073
1074    rit = nextRule( rit, rend );
1075    if( rit )
1076    {
1077        pos = *spos;
1078        goto match;
1079    }
1080    return 0;
1081}
1082
1083
1084/*==========================================================================*/
1085
1086
1087#define REF_PARSE_ALL   a1+2
1088#define REF_PARSE_CASE  a1+3
1089
1090/*
1091