Skip to content

Instantly share code, notes, and snippets.

@Aatch
Created June 23, 2013 08:29
Show Gist options
  • Save Aatch/5844293 to your computer and use it in GitHub Desktop.
Save Aatch/5844293 to your computer and use it in GitHub Desktop.
#[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