[rust-dev] Rust support in the Ragel State Machine Compiler

Erick Tryzelaar erick.tryzelaar at gmail.com
Sat Feb 16 21:23:59 PST 2013


I have a fork of Ragel that supports Rust, which you can find here:
https://github.com/erickt/ragel. I just updated it to support rust
incoming. It performs pretty well too, the url example can parse urls
roughly 2-3 times faster than the hand written parser in the standard
library. I'll try to push my ragel patches upstream one rust 0.6 lands.

For those of you that haven't heard of Ragel, it's part way between regular
expressions and a full parser generator. It builds state machines, and
allows you to manipulate state transitions to parse more complex grammars.
It's pretty neat. For example, here is a simple reverse polish notation
calculator:

https://github.com/erickt/ragel/blob/rust/examples/rust/rpn.rl

%% machine rpn;
%% write data;

fn rpn(data: &str) -> Result<int, ~str> {

    let mut cs = 0;
    let mut p = 0;
    let mut pe = data.len();
    let mut mark = 0;
    let mut st = ~[];

    %%{
        action mark { mark = p; }

        action push {
            let s = data.slice(mark, p);

            match int::from_str(s) {
              None => return Err(fmt!("invalid integer %s", s)),

              Some(i) => st.push(i),
            }

        }
        action add  { let y = st.pop(); let x = st.pop(); st.push(x + y); }

        action sub  { let y = st.pop(); let x = st.pop(); st.push(x - y); }
        action mul  { let y = st.pop(); let x = st.pop(); st.push(x * y); }
        action div  { let y = st.pop(); let x = st.pop(); st.push(x / y); }

        action abs  { let x = st.pop(); st.push(int::abs(x));             }
        action abba { st.push(666); }

        stuff  = digit+ >mark %push
               | '+' @add
               | '-' @sub
               | '*' @mul
               | '/' @div
               | 'abs' %abs
               | 'add' %add
               | 'abba' %abba
               ;


        main := ( space | stuff space )* ;

        write init;
        write exec;
    }%%

    if cs < rpn_first_final {
        if p == pe {
            Err(~"unexpected eof")
        } else {
            Err(fmt!("error at position %u", p))

        }
    } else if st.is_empty() {
        Err(~"rpn stack empty on result")
    } else {
        Ok(st.pop())

    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20130216/f81726b2/attachment.html>


More information about the Rust-dev mailing list