On 11/10/2012 12:59 PM, Karel Sedláček wrote:
Thanks, but could you maybe give me a 10-liner that exemplifies this
kind of behavior inside another application? Let's say I have my own
event loop set up to feed Ragel buffers. Where do I (or does Ragel)
allocate and store it's state? How do I get the pair of functions
described above that are parameterized over the state and consume
incremental new input? Can I have Ragel pass me a bit of userdata as
well, where I can keep the parse state and the thing receiving the
events? Keeping it simple, how about a parser that has an in-action
that tells a C function got_null(void *userdata, size_t start_addr)
whenever it encounters a 0 byte. Prototypes below:

   void got_null(void *userdata, size_t start_addr);
   int parse_null(ragel_state_t *st, void *buf, size_t buf_len, void *userdata);
   int parse_null_eof(rage_state_t *st, void *userdata);

Well, maybe not a 10-liner, but I think I have a single function that might make it clear.

Ragel generates code that uses special named variables. You can either map these to code (as I did with 'stack' and 'eof') or use local variables (like with 'p' and 'pe'). Or, mix and match. You get to persist them however you like.

As you can see, ragel's engine (as I'm using it) is nothing more than a generated while loop state machine. The state is entirely stored in the variables [p, pe, cs] and I give it an rvalue for 'eof'. I'm also using the [stack, top] for recursion ability. You can preserve these state variables however you like.


bool wiki_scanner_scanMore(wiki_scanner_t *scanner) {
    const char
        *p= scanner->curPos,
        *pe= scanner->bufferLimit;
    int cs= scanner->curState;

    log_pos(start);  //macro that prints trace info for debugging

    %%{
        variable stack scanner->stateStack;
        variable top   scanner->stateStackPos;
        variable eof   (scanner->eof? pe : NULL);
        prepush {
            if (scanner->stateStackPos >= scanner->stateStackLen) {
                if (!scanner_enlarge_stateStack(scanner)) {
fprintf(stderr, "ltw_scanner: recursion limit: %d levels deep; scan may emit incorrect results.\n", scanner->stateStackPos);
                    scanner->stateStackPos--;
                }
            }
        }
        write exec;
    }%%

    assert(p == pe);

    scanner->curPos= p;
    scanner->curState= cs;
    return true;
}


Hope that helps.
-Mike


_______________________________________________
ragel-users mailing list
ragel-users@complang.org
http://www.complang.org/mailman/listinfo/ragel-users

Reply via email to