Skip to content

Instantly share code, notes, and snippets.

@brendanzab
Created October 15, 2012 06:29
Show Gist options
  • Save brendanzab/3891072 to your computer and use it in GitHub Desktop.
Save brendanzab/3891072 to your computer and use it in GitHub Desktop.
Baby's First Parser Combinators
fn match_a(s: &str) -> bool { s == "a" }
fn main() {
io::println(fmt!("match_a(\"a\") -> %?", match_a("a")));
io::println(fmt!("match_a(\"b\") -> %?", match_a("b")));
}
fn match_a(s: &s/str) -> Option<&s/str> {
match s == "a" {
true => Some(s),
false => None
}
}
fn main() {
io::println(fmt!("match_a(\"a\") -> %?", match_a("a")));
io::println(fmt!("match_a(\"b\") -> %?", match_a("b")));
}
enum ParseNode {
NonTerminal(~[ParseNode]),
Terminal(~str),
}
enum ParseResult {
ParseOk(ParseNode, ~str),
NoParse,
}
fn match_a(s: &s/str) -> ParseResult {
if s.starts_with("a") {
return ParseOk(Terminal(~"a"), s.slice(1, s.len()));
} else {
return NoParse;
}
}
fn match_b(s: &s/str) -> ParseResult {
if s.starts_with("b") {
return ParseOk(Terminal(~"b"), s.slice(1, s.len()));
} else {
return 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) => return ParseOk(NonTerminal(~[copy a, copy b]), copy tail_b),
NoParse => return NoParse
}
}
NoParse => NoParse
}
}
fn main() {
io::println(fmt!("match_ab(\"ab\") -> %?", match_ab("ab")));
io::println(fmt!("match_ab(\"ba\") -> %?", match_ab("ba")));
io::println(fmt!("match_ab(\"a\") -> %?", match_ab("a")));
io::println(fmt!("match_ab(\"b\") -> %?", match_ab("b")));
io::println(fmt!("match_ab(\"aba\") -> %?", match_ab("abcd")));
}
enum ParseNode {
NonTerminal(~[ParseNode]),
Terminal(~str),
}
enum ParseResult {
ParseOk(ParseNode, ~str),
NoParse,
}
enum Parser {
Concat (@Parser, @Parser),
Alternate (@Parser, @Parser),
Literal (~str),
}
impl Parser {
fn parse(s: &s/str) -> ParseResult {
match self {
Concat(a, b) => {
match a.parse(s) {
ParseOk(node_a, tail_a) => {
match b.parse(tail_a) {
ParseOk(node_b, tail_b) => return ParseOk(NonTerminal(~[copy node_a, copy node_b]), copy tail_b),
NoParse => return NoParse
}
}
NoParse => return NoParse
}
}
Alternate(a, b) => {
match a.parse(s) {
ParseOk(node, tail) => return ParseOk(node, tail),
NoParse => return b.parse(s)
}
}
Literal(name) => {
if s.starts_with(name) {
return ParseOk(Terminal(copy name), s.slice(name.len(), s.len()));
} else {
return NoParse;
}
}
}
}
}
fn main() {
let match_ab = Concat(@Literal(~"a"), @Literal(~"b"));
io::println(fmt!("match_ab.parse(\"ab\") -> %?", match_ab.parse("ab")));
let match_a_or_b = Alternate(@Literal(~"a"), @Literal(~"b"));
io::println(fmt!("match_a_or_b.parse(\"a\") -> %?", match_a_or_b.parse("a")));
io::println(fmt!("match_a_or_b.parse(\"b\") -> %?", match_a_or_b.parse("b")));
io::println(fmt!("match_a_or_b.parse(\"c\") -> %?", match_a_or_b.parse("c")));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment