Skip to content

Instantly share code, notes, and snippets.

@brendanzab
Created October 15, 2012 06:29
Show Gist options
  • Save brendanzab/3891071 to your computer and use it in GitHub Desktop.
Save brendanzab/3891071 to your computer and use it in GitHub Desktop.
Baby's First Parser Combinators
enum ParseNode {
NonTerminal(~[ParseNode]),
Terminal(~str),
}
enum ParseResult {
ParseOk(ParseNode, ~str),
ParseEnd(ParseNode),
NoParse,
}
fn match_a(s: &s/str) -> ParseResult {
if s.starts_with("a") {
let (s_begin, s_end) = (1u, s.len()-1);
if s_end - s_begin < 0 {
ParseEnd(Terminal(~"a"))
} else {
ParseOk(Terminal(~"a"), s.slice(s_begin, s_end))
}
}
else { NoParse }
}
fn match_b(s: &s/str) -> ParseResult {
if s.starts_with("b") {
let (s_begin, s_end) = (1u, s.len()-1);
if s_end - s_begin < 0 {
ParseEnd(Terminal(~"b"))
} else {
ParseOk(Terminal(~"b"), s.slice(s_begin, s_end))
}
}
else { NoParse }
}
fn match_ab(s: &s/str) -> ParseResult {
match match_a(s) {
ParseOk(a, tail_a) => {
match match_b(tail_a) {
ParseOk(b, tail_b) => ParseOk(NonTerminal(~[a, b]), tail_b),
ParseEnd(b) => ParseEnd(NonTerminal(~[a, b])),
NoParse => NoParse
}
}
ParseEnd(_) | NoParse => NoParse
}
}
fn main() {
io::println(fmt!("match_ab(\"ab\") == %?", match_a("ab")));
io::println(fmt!("match_ab(\"ba\") == %?", match_a("ba")));
}
% rustc baby3.rs
baby3.rs:40:69: 40:75 warning: implicitly copying a non-implicitly-copyable value
baby3.rs:40 ParseOk(b, tail_b) => ParseOk(NonTerminal(~[a, b]), tail_b),
^~~~~~
baby3.rs:40:61: 40:62 warning: implicitly copying a non-implicitly-copyable value
baby3.rs:40 ParseOk(b, tail_b) => ParseOk(NonTerminal(~[a, b]), tail_b),
^
baby3.rs:40:64: 40:65 warning: implicitly copying a non-implicitly-copyable value
baby3.rs:40 ParseOk(b, tail_b) => ParseOk(NonTerminal(~[a, b]), tail_b),
^
baby3.rs:41:62: 41:63 warning: implicitly copying a non-implicitly-copyable value
baby3.rs:41 ParseEnd(b) => ParseEnd(NonTerminal(~[a, b])),
^
baby3.rs:41:65: 41:66 warning: implicitly copying a non-implicitly-copyable value
baby3.rs:41 ParseEnd(b) => ParseEnd(NonTerminal(~[a, b])),
^
warning: no debug symbols in executable (-arch x86_64)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment