Created
June 23, 2013 08:29
-
-
Save Aatch/5844293 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[allow(default_methods)]; | |
pub enum ParseResult<T> { | |
Err(ParseError), | |
Ok(T) | |
} | |
pub trait GenParser<T,S,A> { | |
pub fn parse<Tok:TokenStream<T>>(&mut self, &mut ParseState<Tok, S>) -> ParseResult<A>; | |
} | |
pub trait ParserUtil<T,S,A> { | |
pub fn run<Tok:TokenStream<T>>(&mut self, state: S, file: &str, tokens: Tok) -> ParseResult<A>; | |
} | |
impl<T,S,A,G:GenParser<T,S,A>> ParserUtil<T,S,A> for G { | |
pub fn run<Tok:TokenStream<T>>(&mut self, state: S, file: &str, tokens: Tok) -> ParseResult<A> { | |
let mut parse_state = ParseState::new(file.to_owned(), tokens, state); | |
self.parse(&mut parse_state) | |
} | |
} | |
pub trait TokenStream<T:Eq> { | |
pub fn pop_token(&mut self) -> T; | |
pub fn unpop_token(&mut self, t: T); | |
pub fn peek_token(&self) -> T; | |
} | |
struct ParseError { | |
priv col: uint, | |
priv line: uint, | |
priv msg: ~str | |
} | |
struct ParseState<T,S> { | |
priv file: ~str, | |
priv line: uint, | |
priv col: uint, | |
priv toks: T, | |
priv user_state: S | |
} | |
impl<S,T,Tok:TokenStream<T>> ParseState<Tok,S> { | |
pub fn new(filename: ~str, toks: Tok, state: S) -> ParseState<Tok, S> { | |
ParseState { | |
file: filename, | |
line: 0, | |
col: 0, | |
toks: toks, | |
user_state: state | |
} | |
} | |
} | |
impl TokenStream<char> for ~str { | |
pub fn pop_token(&mut self) -> char { | |
self.shift_char() | |
} | |
pub fn unpop_token(&mut self, c: char) { | |
self.unshift_char(c) | |
} | |
pub fn peek_token(&self) -> char { | |
self.char_at(0) | |
} | |
} | |
struct Fail { | |
msg: ~str | |
} | |
impl<T,S,A> GenParser<T,S,A> for Fail { | |
pub fn parse<Tok:TokenStream<T>>(&mut self, st :&mut ParseState<Tok, S>) -> ParseResult<A> { | |
Err(ParseError{ | |
col: st.col, | |
line: st.line, | |
msg: self.msg.clone() | |
}) | |
} | |
} | |
impl Fail { | |
pub fn new(msg: ~str) -> Fail { | |
Fail { | |
msg: msg | |
} | |
} | |
} | |
struct Match<T> { | |
t: T | |
} | |
impl<S,T:Eq> GenParser<T, S, T> for Match <T> { | |
pub fn parse<Tok:TokenStream<T>>(&mut self, st: &mut ParseState<Tok, S>) -> ParseResult<T> { | |
let t = st.toks.peek_token(); | |
if t == self.t { | |
Ok(st.toks.pop_token()) | |
} else { | |
Err(ParseError { | |
col: st.col, | |
line: st.line, | |
msg: fmt!("Expected '%?' found '%?'", self.t, t) | |
}) | |
} | |
} | |
} | |
impl<T> Match<T> { | |
pub fn new(t: T) -> Match<T> { | |
Match { | |
t: t | |
} | |
} | |
} | |
struct Sequence<L,R> { | |
left: L, | |
right: R | |
} | |
impl<T,S,A,B,L:GenParser<T,S,A>,R:GenParser<T,S,B>> Sequence<L,R> { | |
pub fn new(left: L, right: R) -> Sequence<L,R> { | |
Sequence { | |
left: left, | |
right: right | |
} | |
} | |
} | |
impl<T,S,A,B,L:GenParser<T,S,A>,R:GenParser<T,S,B>> GenParser<T,S,B> for Sequence<L,R> { | |
pub fn parse<Tok:TokenStream<T>>(&mut self, st: &mut ParseState<Tok, S>) -> ParseResult<B> { | |
let res = self.left.parse(st); | |
match res { | |
Err(e) => Err(e), | |
_ => self.right.parse(st) | |
} | |
} | |
} | |
fn main() { | |
let mut s = Match::new('S'); | |
let mut o = Match::new('o'); | |
let mut so = Sequence::new(s, o); | |
// ^~~~~~~~~~~~~ | |
// error: cannot determine a type for this bounded type parameter: unconstrained type | |
let a : () = (); | |
let res = so.run(a, "", ~"Something"); | |
match res { | |
Ok(a) => { | |
println(fmt!("%c", a)) | |
} | |
Err(a) => { | |
println(fmt!("Error: %s", a.msg)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment