let users specify fallible rules (and the error type)

This commit is contained in:
Niko Matsakis 2015-07-21 12:45:38 -04:00
parent 69a881d4a5
commit 1bbfb9d764
18 changed files with 4437 additions and 4153 deletions

View File

@ -0,0 +1,28 @@
use util::tok::Tok;
use lalrpop_util::ParseError;
grammar;
extern token {
type Location = usize;
type Error = char;
enum Tok {
"-" => Tok::Minus(..),
"+" => Tok::Plus(..)
}
}
pub Items: Vec<(usize, usize)> = {
=> vec![];
Items "+" =>? {
Err(ParseError::User { error: '+' })
};
<v:Items> "-" =>? Ok(v);
};
Spanned<T>: (usize, usize) = {
<@L> T <@R> => (<>);
};

301
lalrpop-test/src/error.rs Normal file
View File

@ -0,0 +1,301 @@
#![allow(unused_imports)]
use util::tok::Tok;
use lalrpop_util::ParseError;
extern crate lalrpop_util as __lalrpop_util;
use self::__lalrpop_util::ParseError as __ParseError;
#[allow(non_snake_case)]
pub fn parse_Items<
__TOKEN: __ToTriple<Error=char>,
__TOKENS: IntoIterator<Item=__TOKEN>,
>(
__tokens: __TOKENS,
) -> Result<Vec<(usize, usize)>, __ParseError<usize,Tok,char>>
{
let mut __tokens = __tokens.into_iter();
let mut __tokens = __tokens.map(|t| __ToTriple::to_triple(t));
let __lookahead = match __tokens.next() { Some(Ok(v)) => Some(v), None => None, Some(Err(e)) => return Err(__ParseError::User { error: e }) };
match try!(__parse__Items::__state0(None, __lookahead, &mut __tokens)) {
(_, Some(__lookahead), _) => {
Err(__ParseError::ExtraToken { token: __lookahead })
}
(_, None, __parse__Items::__Nonterminal::____Items(__nt)) => {
Ok(__nt)
}
_ => unreachable!(),
}
}
mod __parse__Items {
#![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports)]
use util::tok::Tok;
use lalrpop_util::ParseError;
extern crate lalrpop_util as __lalrpop_util;
use self::__lalrpop_util::ParseError as __ParseError;
use super::__ToTriple;
pub enum __Nonterminal<> {
____Items(Vec<(usize, usize)>),
Items(Vec<(usize, usize)>),
}
// State 0
// Items = (*) [EOF]
// Items = (*) ["+"]
// Items = (*) ["-"]
// Items = (*) Items "+" [EOF]
// Items = (*) Items "+" ["+"]
// Items = (*) Items "+" ["-"]
// Items = (*) Items "-" [EOF]
// Items = (*) Items "-" ["+"]
// Items = (*) Items "-" ["-"]
// __Items = (*) Items [EOF]
//
// EOF -> Reduce(Items = => Call(ActionFn(1));)
// "+" -> Reduce(Items = => Call(ActionFn(1));)
// "-" -> Reduce(Items = => Call(ActionFn(1));)
//
// Items -> S1
pub fn __state0<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),char>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,char>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
None => {
let __nt = super::__action1();
__result = (__lookbehind, __lookahead, __Nonterminal::Items(__nt));
}
Some((_, Tok::Plus(..), _)) => {
let __nt = super::__action1();
__result = (__lookbehind, __lookahead, __Nonterminal::Items(__nt));
}
Some((_, Tok::Minus(..), _)) => {
let __nt = super::__action1();
__result = (__lookbehind, __lookahead, __Nonterminal::Items(__nt));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
loop {
let (__lookbehind, __lookahead, __nt) = __result;
match __nt {
__Nonterminal::Items(__nt) => {
let __sym0 = &mut Some(__nt);
__result = try!(__state1(__lookbehind, __lookahead, __tokens, __sym0));
}
_ => {
return Ok((__lookbehind, __lookahead, __nt));
}
}
}
}
// State 1
// Items = Items (*) "+" [EOF]
// Items = Items (*) "+" ["+"]
// Items = Items (*) "+" ["-"]
// Items = Items (*) "-" [EOF]
// Items = Items (*) "-" ["+"]
// Items = Items (*) "-" ["-"]
// __Items = Items (*) [EOF]
//
// "-" -> Shift(S3)
// "+" -> Shift(S2)
// EOF -> Reduce(__Items = Items => Call(ActionFn(0));)
//
pub fn __state1<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),char>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,char>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, __tok @ Tok::Minus(..), __loc)) => {
let mut __lookbehind = Some(__loc);
let mut __sym1 = &mut Some((__tok));
let __lookahead = match __tokens.next() { Some(Ok(v)) => Some(v), None => None, Some(Err(e)) => return Err(__ParseError::User { error: e }) };
__result = try!(__state3(__lookbehind, __lookahead, __tokens, __sym0, __sym1));
}
Some((_, __tok @ Tok::Plus(..), __loc)) => {
let mut __lookbehind = Some(__loc);
let mut __sym1 = &mut Some((__tok));
let __lookahead = match __tokens.next() { Some(Ok(v)) => Some(v), None => None, Some(Err(e)) => return Err(__ParseError::User { error: e }) };
__result = try!(__state2(__lookbehind, __lookahead, __tokens, __sym0, __sym1));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __nt = super::__action0(__sym0);
return Ok((__lookbehind, __lookahead, __Nonterminal::____Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
return Ok(__result);
}
// State 2
// Items = Items "+" (*) [EOF]
// Items = Items "+" (*) ["+"]
// Items = Items "+" (*) ["-"]
//
// "-" -> Reduce(Items = Items, "+" => TryCall(ActionFn(2));)
// "+" -> Reduce(Items = Items, "+" => TryCall(ActionFn(2));)
// EOF -> Reduce(Items = Items, "+" => TryCall(ActionFn(2));)
//
pub fn __state2<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),char>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,char>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action2(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action2(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action2(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 3
// Items = Items "-" (*) [EOF]
// Items = Items "-" (*) ["+"]
// Items = Items "-" (*) ["-"]
//
// "-" -> Reduce(Items = Items, "-" => TryCall(ActionFn(3));)
// EOF -> Reduce(Items = Items, "-" => TryCall(ActionFn(3));)
// "+" -> Reduce(Items = Items, "-" => TryCall(ActionFn(3));)
//
pub fn __state3<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),char>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,char>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action3(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action3(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = try!(super::__action3(__sym0, __sym1));
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
}
pub fn __action0<
>(
__0: Vec<(usize, usize)>,
) -> Vec<(usize, usize)>
{
(__0)
}
pub fn __action1<
>(
) -> Vec<(usize, usize)>
{
vec![]
}
pub fn __action2<
>(
__0: Vec<(usize, usize)>,
__1: Tok,
) -> Result<Vec<(usize, usize)>,__ParseError<usize,Tok,char>>
{
{
Err(ParseError::User { error: '+' })
}
}
pub fn __action3<
>(
v: Vec<(usize, usize)>,
_: Tok,
) -> Result<Vec<(usize, usize)>,__ParseError<usize,Tok,char>>
{
Ok(v)
}
pub trait __ToTriple {
type Error;
fn to_triple(value: Self) -> Result<(usize,Tok,usize),Self::Error>;
}
impl __ToTriple for (usize, Tok, usize) {
type Error = char;
fn to_triple(value: Self) -> Result<(usize,Tok,usize),char> {
Ok(value)
}
}
impl<ERROR> __ToTriple for Result<(usize, Tok, usize),ERROR> {
type Error = ERROR;
fn to_triple(value: Self) -> Result<(usize,Tok,usize),ERROR> {
value
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,11 @@ extern crate lalrpop_util as __lalrpop_util;
use self::__lalrpop_util::ParseError as __ParseError;
#[allow(non_snake_case)]
pub fn parse_Items<
__ERROR,
__TOKEN: __ToTriple<Error=__ERROR>,
__TOKEN: __ToTriple<Error=()>,
__TOKENS: IntoIterator<Item=__TOKEN>,
>(
__tokens: __TOKENS,
) -> Result<Vec<(usize, usize)>, __ParseError<usize,Tok,__ERROR>>
) -> Result<Vec<(usize, usize)>, __ParseError<usize,Tok,()>>
{
let mut __tokens = __tokens.into_iter();
let mut __tokens = __tokens.map(|t| __ToTriple::to_triple(t));
@ -34,11 +33,11 @@ mod __parse__Items {
use super::__ToTriple;
pub enum __Nonterminal<> {
____Items(Vec<(usize, usize)>),
Items(Vec<(usize, usize)>),
Spanned_3c_22_2b_22_3e((usize, usize)),
_40L(usize),
Items(Vec<(usize, usize)>),
_40R(usize),
_40L(usize),
____Items(Vec<(usize, usize)>),
}
// State 0
@ -60,16 +59,15 @@ mod __parse__Items {
// EOF -> Reduce(@L = => Lookahead;)
// "+" -> Reduce(@L = => Lookahead;)
//
// @L -> S1
// Items -> S2
// @L -> S1
pub fn __state0<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
@ -95,14 +93,14 @@ mod __parse__Items {
loop {
let (__lookbehind, __lookahead, __nt) = __result;
match __nt {
__Nonterminal::_40L(__nt) => {
let __sym0 = &mut Some(__nt);
__result = try!(__state1(__lookbehind, __lookahead, __tokens, __sym0));
}
__Nonterminal::Items(__nt) => {
let __sym0 = &mut Some(__nt);
__result = try!(__state2(__lookbehind, __lookahead, __tokens, __sym0));
}
__Nonterminal::_40L(__nt) => {
let __sym0 = &mut Some(__nt);
__result = try!(__state1(__lookbehind, __lookahead, __tokens, __sym0));
}
_ => {
return Ok((__lookbehind, __lookahead, __nt));
}
@ -118,24 +116,23 @@ mod __parse__Items {
// Items = @L (*) @R ["+"]
// Items = @L (*) @R ["-"]
//
// EOF -> Reduce(@R = => Lookbehind;)
// "-" -> Reduce(@R = => Lookbehind;)
// "+" -> Reduce(@R = => Lookbehind;)
// "-" -> Reduce(@R = => Lookbehind;)
// EOF -> Reduce(@R = => Lookbehind;)
//
// @R -> S3
pub fn __state1<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<usize>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
None => {
Some((_, Tok::Plus(..), _)) => {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
@ -143,7 +140,7 @@ mod __parse__Items {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
Some((_, Tok::Plus(..), _)) => {
None => {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
@ -183,20 +180,19 @@ mod __parse__Items {
// __Items = Items (*) [EOF]
//
// "+" -> Reduce(@L = => Lookahead;)
// "-" -> Shift(S6)
// EOF -> Reduce(__Items = Items => Call(ActionFn(0));)
// "-" -> Shift(S4)
//
// @L -> S6
// Spanned<"+"> -> S5
// @L -> S4
pub fn __state2<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
@ -204,7 +200,7 @@ mod __parse__Items {
let mut __lookbehind = Some(__loc);
let mut __sym1 = &mut Some((__tok));
let __lookahead = match __tokens.next() { Some(Ok(v)) => Some(v), None => None, Some(Err(e)) => return Err(__ParseError::User { error: e }) };
__result = try!(__state4(__lookbehind, __lookahead, __tokens, __sym0, __sym1));
__result = try!(__state6(__lookbehind, __lookahead, __tokens, __sym0, __sym1));
}
Some((_, Tok::Plus(..), _)) => {
let __nt = __lookahead.as_ref().map(|o| ::std::clone::Clone::clone(&o.0)).or_else(|| ::std::clone::Clone::clone(&__lookbehind)).unwrap_or_default();
@ -225,14 +221,14 @@ mod __parse__Items {
while __sym0.is_some() {
let (__lookbehind, __lookahead, __nt) = __result;
match __nt {
__Nonterminal::_40L(__nt) => {
let __sym1 = &mut Some(__nt);
__result = try!(__state6(__lookbehind, __lookahead, __tokens, __sym1));
}
__Nonterminal::Spanned_3c_22_2b_22_3e(__nt) => {
let __sym1 = &mut Some(__nt);
__result = try!(__state5(__lookbehind, __lookahead, __tokens, __sym0, __sym1));
}
__Nonterminal::_40L(__nt) => {
let __sym1 = &mut Some(__nt);
__result = try!(__state4(__lookbehind, __lookahead, __tokens, __sym1));
}
_ => {
return Ok((__lookbehind, __lookahead, __nt));
}
@ -246,24 +242,23 @@ mod __parse__Items {
// Items = @L @R (*) ["+"]
// Items = @L @R (*) ["-"]
//
// "+" -> Reduce(Items = @L, @R => Call(ActionFn(1));)
// "-" -> Reduce(Items = @L, @R => Call(ActionFn(1));)
// EOF -> Reduce(Items = @L, @R => Call(ActionFn(1));)
// "-" -> Reduce(Items = @L, @R => Call(ActionFn(1));)
// "+" -> Reduce(Items = @L, @R => Call(ActionFn(1));)
//
pub fn __state3<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<usize>,
__sym1: &mut Option<usize>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Plus(..), _)) => {
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action1(__sym0, __sym1);
@ -275,7 +270,7 @@ mod __parse__Items {
let __nt = super::__action1(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action1(__sym0, __sym1);
@ -291,119 +286,20 @@ mod __parse__Items {
}
// State 4
// Items = Items "-" (*) [EOF]
// Items = Items "-" (*) ["+"]
// Items = Items "-" (*) ["-"]
//
// "+" -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
// "-" -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
// EOF -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
//
pub fn __state4<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 5
// Items = Items Spanned<"+"> (*) [EOF]
// Items = Items Spanned<"+"> (*) ["+"]
// Items = Items Spanned<"+"> (*) ["-"]
//
// "-" -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
// "+" -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
// EOF -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
//
pub fn __state5<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<(usize, usize)>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 6
// Spanned<"+"> = @L (*) "+" @R [EOF]
// Spanned<"+"> = @L (*) "+" @R ["+"]
// Spanned<"+"> = @L (*) "+" @R ["-"]
//
// "+" -> Shift(S7)
//
pub fn __state6<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
pub fn __state4<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<usize>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
@ -423,6 +319,102 @@ mod __parse__Items {
return Ok(__result);
}
// State 5
// Items = Items Spanned<"+"> (*) [EOF]
// Items = Items Spanned<"+"> (*) ["+"]
// Items = Items Spanned<"+"> (*) ["-"]
//
// EOF -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
// "-" -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
// "+" -> Reduce(Items = Items, Spanned<"+"> => Call(ActionFn(2));)
//
pub fn __state5<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<(usize, usize)>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action2(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 6
// Items = Items "-" (*) [EOF]
// Items = Items "-" (*) ["+"]
// Items = Items "-" (*) ["-"]
//
// "-" -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
// EOF -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
// "+" -> Reduce(Items = Items, "-" => Call(ActionFn(3));)
//
pub fn __state6<
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Vec<(usize, usize)>>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
Some((_, Tok::Minus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __nt = super::__action3(__sym0, __sym1);
return Ok((__lookbehind, __lookahead, __Nonterminal::Items(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 7
// @R = (*) [EOF]
// @R = (*) ["+"]
@ -432,20 +424,19 @@ mod __parse__Items {
// Spanned<"+"> = @L "+" (*) @R ["-"]
//
// "-" -> Reduce(@R = => Lookbehind;)
// "+" -> Reduce(@R = => Lookbehind;)
// EOF -> Reduce(@R = => Lookbehind;)
// "+" -> Reduce(@R = => Lookbehind;)
//
// @R -> S8
pub fn __state7<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<usize>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
@ -453,11 +444,11 @@ mod __parse__Items {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
Some((_, Tok::Plus(..), _)) => {
None => {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
None => {
Some((_, Tok::Plus(..), _)) => {
let __nt = ::std::clone::Clone::clone(&__lookbehind).unwrap_or_default();
__result = (__lookbehind, __lookahead, __Nonterminal::_40R(__nt));
}
@ -489,12 +480,11 @@ mod __parse__Items {
// Spanned<"+"> = @L "+" @R (*) ["-"]
//
// "-" -> Reduce(Spanned<"+"> = @L, "+", @R => Call(ActionFn(4));)
// "+" -> Reduce(Spanned<"+"> = @L, "+", @R => Call(ActionFn(4));)
// EOF -> Reduce(Spanned<"+"> = @L, "+", @R => Call(ActionFn(4));)
// "+" -> Reduce(Spanned<"+"> = @L, "+", @R => Call(ActionFn(4));)
//
pub fn __state8<
__ERROR,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),__ERROR>>,
__TOKENS: Iterator<Item=Result<(usize, Tok, usize),()>>,
>(
__lookbehind: Option<usize>,
__lookahead: Option<(usize, Tok, usize)>,
@ -502,7 +492,7 @@ mod __parse__Items {
__sym0: &mut Option<usize>,
__sym1: &mut Option<Tok>,
__sym2: &mut Option<usize>,
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,__ERROR>>
) -> Result<(Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>), __ParseError<usize,Tok,()>>
{
let mut __result: (Option<usize>, Option<(usize, Tok, usize)>, __Nonterminal<>);
match __lookahead {
@ -513,14 +503,14 @@ mod __parse__Items {
let __nt = super::__action4(__sym0, __sym1, __sym2);
return Ok((__lookbehind, __lookahead, __Nonterminal::Spanned_3c_22_2b_22_3e(__nt)));
}
Some((_, Tok::Plus(..), _)) => {
None => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __sym2 = __sym2.take().unwrap();
let __nt = super::__action4(__sym0, __sym1, __sym2);
return Ok((__lookbehind, __lookahead, __Nonterminal::Spanned_3c_22_2b_22_3e(__nt)));
}
None => {
Some((_, Tok::Plus(..), _)) => {
let __sym0 = __sym0.take().unwrap();
let __sym1 = __sym1.take().unwrap();
let __sym2 = __sym2.take().unwrap();

View File

@ -20,6 +20,9 @@ mod loc;
/// test that uses `super` in paths in various places
mod use_super;
/// test that exercises locations and spans
mod error;
mod util;
/// This constant is here so that some of the generator parsers can
@ -120,3 +123,14 @@ fn use_super_test1() {
util::test(|v| use_super::parse_S(v), "()", 0);
}
#[test]
fn error_test1() {
use lalrpop_util::ParseError;
match util::test_err_gen(error::parse_Items, "---+") {
Err(ParseError::User { error: '+' }) => { /* OK! */ }
r => {
panic!("unexpected response from parser: {:?}", r);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,11 @@ extern crate lalrpop_util as __lalrpop_util;
use self::__lalrpop_util::ParseError as __ParseError;
#[allow(non_snake_case)]
pub fn parse_S<
__ERROR,
__TOKEN: __ToTriple<Error=__ERROR>,
__TOKEN: __ToTriple<Error=()>,
__TOKENS: IntoIterator<Item=__TOKEN>,
>(
__tokens: __TOKENS,
) -> Result<i32, __ParseError<(),Tok,__ERROR>>
) -> Result<i32, __ParseError<(),Tok,()>>
{
let mut __tokens = __tokens.into_iter();
let mut __tokens = __tokens.map(|t| __ToTriple::to_triple(t));
@ -34,25 +33,24 @@ mod __parse__S {
use super::__ToTriple;
pub enum __Nonterminal<> {
S(i32),
____S(i32),
S(i32),
}
// State 0
// S = (*) "(" ")" [EOF]
// __S = (*) S [EOF]
//
// "(" -> Shift(S2)
// "(" -> Shift(S1)
//
// S -> S1
// S -> S2
pub fn __state0<
__ERROR,
__TOKENS: Iterator<Item=Result<((), Tok, ()),__ERROR>>,
__TOKENS: Iterator<Item=Result<((), Tok, ()),()>>,
>(
__lookbehind: Option<()>,
__lookahead: Option<((), Tok, ())>,
__tokens: &mut __TOKENS,
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,__ERROR>>
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,()>>
{
let mut __result: (Option<()>, Option<((), Tok, ())>, __Nonterminal<>);
match __lookahead {
@ -60,7 +58,7 @@ mod __parse__S {
let mut __lookbehind = Some(__loc);
let mut __sym0 = &mut Some((__tok));
let __lookahead = match __tokens.next() { Some(Ok(v)) => Some(v), None => None, Some(Err(e)) => return Err(__ParseError::User { error: e }) };
__result = try!(__state2(__lookbehind, __lookahead, __tokens, __sym0));
__result = try!(__state1(__lookbehind, __lookahead, __tokens, __sym0));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
@ -74,7 +72,7 @@ mod __parse__S {
match __nt {
__Nonterminal::S(__nt) => {
let __sym0 = &mut Some(__nt);
__result = try!(__state1(__lookbehind, __lookahead, __tokens, __sym0));
__result = try!(__state2(__lookbehind, __lookahead, __tokens, __sym0));
}
_ => {
return Ok((__lookbehind, __lookahead, __nt));
@ -84,50 +82,18 @@ mod __parse__S {
}
// State 1
// __S = S (*) [EOF]
//
// EOF -> Reduce(__S = S => Call(ActionFn(0));)
//
pub fn __state1<
__ERROR,
__TOKENS: Iterator<Item=Result<((), Tok, ()),__ERROR>>,
>(
__lookbehind: Option<()>,
__lookahead: Option<((), Tok, ())>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<i32>,
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,__ERROR>>
{
let mut __result: (Option<()>, Option<((), Tok, ())>, __Nonterminal<>);
match __lookahead {
None => {
let __sym0 = __sym0.take().unwrap();
let __nt = super::__action0(__sym0);
return Ok((__lookbehind, __lookahead, __Nonterminal::____S(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 2
// S = "(" (*) ")" [EOF]
//
// ")" -> Shift(S3)
//
pub fn __state2<
__ERROR,
__TOKENS: Iterator<Item=Result<((), Tok, ()),__ERROR>>,
pub fn __state1<
__TOKENS: Iterator<Item=Result<((), Tok, ()),()>>,
>(
__lookbehind: Option<()>,
__lookahead: Option<((), Tok, ())>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Tok>,
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,__ERROR>>
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,()>>
{
let mut __result: (Option<()>, Option<((), Tok, ())>, __Nonterminal<>);
match __lookahead {
@ -147,21 +113,50 @@ mod __parse__S {
return Ok(__result);
}
// State 2
// __S = S (*) [EOF]
//
// EOF -> Reduce(__S = S => Call(ActionFn(0));)
//
pub fn __state2<
__TOKENS: Iterator<Item=Result<((), Tok, ()),()>>,
>(
__lookbehind: Option<()>,
__lookahead: Option<((), Tok, ())>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<i32>,
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,()>>
{
let mut __result: (Option<()>, Option<((), Tok, ())>, __Nonterminal<>);
match __lookahead {
None => {
let __sym0 = __sym0.take().unwrap();
let __nt = super::__action0(__sym0);
return Ok((__lookbehind, __lookahead, __Nonterminal::____S(__nt)));
}
_ => {
return Err(__ParseError::UnrecognizedToken {
token: __lookahead,
expected: vec![],
});
}
}
}
// State 3
// S = "(" ")" (*) [EOF]
//
// EOF -> Reduce(S = "(", ")" => Call(ActionFn(1));)
//
pub fn __state3<
__ERROR,
__TOKENS: Iterator<Item=Result<((), Tok, ()),__ERROR>>,
__TOKENS: Iterator<Item=Result<((), Tok, ()),()>>,
>(
__lookbehind: Option<()>,
__lookahead: Option<((), Tok, ())>,
__tokens: &mut __TOKENS,
__sym0: &mut Option<Tok>,
__sym1: &mut Option<Tok>,
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,__ERROR>>
) -> Result<(Option<()>, Option<((), Tok, ())>, __Nonterminal<>), __ParseError<(),Tok,()>>
{
let mut __result: (Option<()>, Option<((), Tok, ())>, __Nonterminal<>);
match __lookahead {

View File

@ -39,3 +39,13 @@ pub fn test_loc<R:Debug+Eq,F>(parse_fn: F,
// expect output to be correct
assert!(r == expected, "parsing {:?}, got {:#?}, expected {:#?}", input, r, expected);
}
pub fn test_err_gen<R,F>(parse_fn: F, input: &str) -> R
where F: FnOnce(Vec<(usize, Tok, usize)>) -> R
{
// create tokens
let tokens = tok::tokenize(input);
// parse, expecting input to be totally consumed
parse_fn(tokens)
}

View File

@ -44,6 +44,7 @@ pub enum ParseError<L,T,E> {
/// A richer alternative to `Message`, error objects offer more
/// information and reflection.
ErrorObject {
span: Option<(L, L)>,
error: Box<Error>,
},
@ -53,3 +54,8 @@ pub enum ParseError<L,T,E> {
},
}
impl<L,T,E> ParseError<L,T,E> {
pub fn message(text: String) -> ParseError<L,T,E> {
ParseError::Message { message: text }
}
}

View File

@ -162,6 +162,18 @@ fn emit_action_code<W:Write>(grammar: &r::Grammar,
{
for (i, defn) in grammar.action_fn_defns.iter().enumerate() {
rust!(rust, "");
let ret_type = if defn.fallible {
format!("Result<{},{}ParseError<{},{},{}>>",
defn.ret_type,
grammar.prefix,
grammar.types.terminal_loc_type(),
grammar.types.terminal_enum_type(),
grammar.types.error_type())
} else {
format!("{}", defn.ret_type)
};
try!(rust.write_pub_fn_header(
grammar,
format!("{}action{}", grammar.prefix, i),
@ -170,7 +182,7 @@ fn emit_action_code<W:Write>(grammar: &r::Grammar,
.zip(defn.arg_types.iter())
.map(|(p, t)| format!("{}: {}", p, t))
.collect(),
format!("{}", defn.ret_type),
ret_type,
vec![]));
rust!(rust, "{{");
rust!(rust, "{}", defn.code);
@ -186,42 +198,43 @@ fn emit_to_triple_trait<W:Write>(grammar: &r::Grammar,
#![allow(non_snake_case)]
let L = grammar.types.terminal_loc_type();
let E = grammar.types.terminal_enum_type();
let T = grammar.types.terminal_enum_type();
let E = grammar.types.error_type();
rust!(rust, "");
rust!(rust, "pub trait {}ToTriple {{", grammar.prefix);
rust!(rust, "type Error;");
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),Self::Error>;", L, E, L);
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),Self::Error>;", L, T, L);
rust!(rust, "}}");
rust!(rust, "");
if grammar.types.opt_terminal_loc_type().is_some() {
rust!(rust, "impl {}ToTriple for ({}, {}, {}) {{",
grammar.prefix, L, E, L);
rust!(rust, "type Error = ();");
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),()> {{", L, E, L);
grammar.prefix, L, T, L);
rust!(rust, "type Error = {};", E);
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),{}> {{", L, T, L, E);
rust!(rust, "Ok(value)");
rust!(rust, "}}");
rust!(rust, "}}");
rust!(rust, "impl<ERROR> {}ToTriple for Result<({}, {}, {}),ERROR> {{",
grammar.prefix, L, E, L);
grammar.prefix, L, T, L);
rust!(rust, "type Error = ERROR;");
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),ERROR> {{", L, E, L);
rust!(rust, "fn to_triple(value: Self) -> Result<({},{},{}),ERROR> {{", L, T, L);
rust!(rust, "value");
rust!(rust, "}}");
rust!(rust, "}}");
} else {
rust!(rust, "impl {}ToTriple for {} {{", grammar.prefix, E);
rust!(rust, "type Error = ();");
rust!(rust, "fn to_triple(value: Self) -> Result<((),{},()),()> {{", E);
rust!(rust, "impl {}ToTriple for {} {{", grammar.prefix, T);
rust!(rust, "type Error = {};", E);
rust!(rust, "fn to_triple(value: Self) -> Result<((),{},()),{}> {{", T, E);
rust!(rust, "Ok(((), value, ()))");
rust!(rust, "}}");
rust!(rust, "}}");
rust!(rust, "impl<ERROR> {}ToTriple for Result<({}),ERROR> {{", grammar.prefix, E);
rust!(rust, "impl<ERROR> {}ToTriple for Result<({}),ERROR> {{", grammar.prefix, T);
rust!(rust, "type Error = ERROR;");
rust!(rust, "fn to_triple(value: Self) -> Result<((),{},()),ERROR> {{", E);
rust!(rust, "fn to_triple(value: Self) -> Result<((),{},()),ERROR> {{", T);
rust!(rust, "value.map(|v| ((), v, ()))");
rust!(rust, "}}");
rust!(rust, "}}");

View File

@ -48,6 +48,9 @@ pub struct AssociatedType {
/// Recognized associated type for the token location
pub const LOCATION: &'static str = "Location";
/// Recognized associated type for custom errors
pub const ERROR: &'static str = "Error";
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EnumToken {
pub type_name: TypeRef,
@ -134,6 +137,7 @@ pub struct Alternative {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ActionKind {
User(String),
Fallible(String),
Lookahead,
Lookbehind,
}

View File

@ -74,6 +74,7 @@ pub enum Symbol {
pub enum ActionKind {
// execute code provided by the user
Call(ActionFn),
TryCall(ActionFn),
Lookahead,
Lookbehind,
}
@ -83,6 +84,7 @@ pub struct ActionFnDefn {
pub arg_patterns: Vec<InternedString>,
pub arg_types: Vec<TypeRepr>,
pub ret_type: TypeRepr,
pub fallible: bool,
pub code: String,
}
@ -108,6 +110,7 @@ pub struct NominalTypeRepr {
pub struct Types {
terminal_enum_type: NominalTypeRepr,
terminal_loc_type: Option<TypeRepr>,
error_type: Option<TypeRepr>,
default_terminal_type: TypeRepr,
terminal_types: Map<TerminalString, TypeRepr>,
nonterminal_types: Map<NonterminalString, TypeRepr>
@ -115,9 +118,11 @@ pub struct Types {
impl Types {
pub fn new(terminal_loc_type: Option<TypeRepr>,
error_type: Option<TypeRepr>,
terminal_enum_type: NominalTypeRepr)
-> Types {
Types { terminal_loc_type: terminal_loc_type,
error_type: error_type,
terminal_enum_type: terminal_enum_type.clone(),
terminal_types: map(),
default_terminal_type: TypeRepr::Nominal(terminal_enum_type),
@ -145,6 +150,11 @@ impl Types {
.unwrap_or_else(|| TypeRepr::Tuple(vec![]))
}
pub fn error_type(&self) -> TypeRepr {
self.error_type.clone()
.unwrap_or_else(|| TypeRepr::Tuple(vec![]))
}
pub fn terminal_type(&self, id: TerminalString) -> &TypeRepr {
self.terminal_types.get(&id).unwrap_or(&self.default_terminal_type)
}

View File

@ -110,20 +110,20 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> {
// input as `Foo`. An error is reported if the entire input is not
// consumed.
fn write_start_fn(&mut self) -> io::Result<()> {
let error_type = self.error_type();
let error_type = self.types.error_type();
let parse_error_type = self.parse_error_type();
rust!(self.out, "#[allow(non_snake_case)]");
try!(self.out.write_pub_fn_header(
self.grammar,
format!("parse_{}", self.user_start_symbol),
vec![format!("{}ERROR", self.prefix),
format!("{}TOKEN: {}ToTriple<Error={}ERROR>",
self.prefix, self.prefix, self.prefix),
vec![format!("{}TOKEN: {}ToTriple<Error={}>",
self.prefix, self.prefix, error_type),
format!("{}TOKENS: IntoIterator<Item={}TOKEN>", self.prefix, self.prefix)],
vec![format!("{}tokens: {}TOKENS", self.prefix, self.prefix)],
format!("Result<{}, {}>",
self.types.nonterminal_type(self.start_symbol),
error_type),
parse_error_type),
vec![]));
rust!(self.out, "{{");
@ -164,7 +164,8 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> {
let this_prefix = self.state_prefixes[this_index.0];
let loc_type = self.types.terminal_loc_type();
let triple_type = self.triple_type();
let error_type = self.error_type();
let parse_error_type = self.parse_error_type();
let error_type = self.types.error_type();
// Leave a comment explaining what this state is.
rust!(self.out, "// State {}", this_index.0);
@ -196,15 +197,14 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> {
try!(self.out.write_pub_fn_header(
self.grammar,
format!("{}state{}", self.prefix, this_index.0),
vec![format!("{}ERROR", self.prefix),
format!("{}TOKENS: Iterator<Item=Result<{},{}ERROR>>",
self.prefix, triple_type, self.prefix)],
vec![format!("{}TOKENS: Iterator<Item=Result<{},{}>>",
self.prefix, triple_type, error_type)],
base_args.into_iter().chain(sym_args).collect(),
format!("Result<(Option<{}>, Option<{}>, {}Nonterminal<{}>), {}>",
loc_type,
triple_type, self.prefix,
self.grammar.user_type_parameter_refs(),
error_type),
parse_error_type),
vec![]));
rust!(self.out, "{{");
@ -275,6 +275,15 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> {
Sep(", ", &transfer_syms))
}
ActionKind::TryCall(action_fn) => {
rust!(self.out, "let {}nt = try!(super::{}action{}({}{}));",
self.prefix,
self.prefix,
action_fn.index(),
self.grammar.user_parameter_refs(),
Sep(", ", &transfer_syms))
}
ActionKind::Lookahead => {
// take the lookahead, if any; otherwise, we are
// at EOF, so taker the lookbehind (end of last
@ -455,12 +464,12 @@ impl<'ascent,'grammar,W:Write> RecursiveAscent<'ascent,'grammar,W> {
self.types.triple_type()
}
fn error_type(&mut self) -> String {
format!("{}ParseError<{},{},{}ERROR>",
fn parse_error_type(&mut self) -> String {
format!("{}ParseError<{},{},{}>",
self.prefix,
self.types.terminal_loc_type(),
self.types.terminal_enum_type(),
self.prefix)
self.types.error_type())
}
fn next_token(&mut self, tokens: &str) -> String {

View File

@ -125,7 +125,7 @@ impl LowerState {
pt::SymbolKind::Nonterminal(fake_name))]
};
let symbols = vec![r::Symbol::Nonterminal(nt.name)];
let action_fn = self.action_fn(nt_type, &expr, &symbols, None);
let action_fn = self.action_fn(nt_type, false, &expr, &symbols, None);
self.productions.push(r::Production {
nonterminal: fake_name,
symbols: symbols,
@ -150,11 +150,15 @@ impl LowerState {
Some(pt::ActionKind::Lookbehind) =>
r::ActionKind::Lookbehind,
Some(pt::ActionKind::User(string)) => {
let action_fn = self.action_fn(nt_type, &expr, &symbols, Some(string));
let action_fn = self.action_fn(nt_type, false, &expr, &symbols, Some(string));
r::ActionKind::Call(action_fn)
}
Some(pt::ActionKind::Fallible(string)) => {
let action_fn = self.action_fn(nt_type, true, &expr, &symbols, Some(string));
r::ActionKind::TryCall(action_fn)
}
None => {
let action_fn = self.action_fn(nt_type, &expr, &symbols, None);
let action_fn = self.action_fn(nt_type, false, &expr, &symbols, None);
r::ActionKind::Call(action_fn)
}
}
@ -162,6 +166,7 @@ impl LowerState {
fn action_fn(&mut self,
nt_type: r::TypeRepr,
fallible: bool,
expr: &pt::ExprSymbol,
symbols: &[r::Symbol],
action: Option<String>)
@ -192,6 +197,7 @@ impl LowerState {
arg_patterns: arg_patterns,
arg_types: arg_types,
ret_type: nt_type,
fallible: fallible,
code: action
}
}
@ -211,6 +217,7 @@ impl LowerState {
arg_patterns: arg_patterns,
arg_types: arg_types,
ret_type: nt_type,
fallible: fallible,
code: action
}
}

View File

@ -3,7 +3,7 @@ use super::norm_util::{self, AlternativeAction, Symbols};
use std::collections::{HashMap};
use grammar::parse_tree::{ActionKind, Alternative,
ExternToken,
ERROR, ExternToken,
Grammar, GrammarItem,
LOCATION,
NonterminalData, NonterminalString,
@ -65,12 +65,15 @@ impl<'grammar> TypeInferencer<'grammar> {
let loc_type = extern_token.associated_type(intern(LOCATION))
.map(|tr| tr.type_ref.type_repr());
let error_type = extern_token.associated_type(intern(ERROR))
.map(|tr| tr.type_ref.type_repr());
let enum_type = match extern_token.enum_token.type_name.type_repr() {
TypeRepr::Nominal(data) => data,
_ => panic!("enum token without nominal type passed validation")
};
let mut types = Types::new(loc_type, enum_type);
let mut types = Types::new(loc_type, error_type, enum_type);
// For each defined conversion, figure out the type of the
// terminal and enter it into `types` by hand if it is not the
@ -224,7 +227,8 @@ impl<'grammar> TypeInferencer<'grammar> {
fn alternative_type(&mut self, alt: &Alternative) -> NormResult<TypeRepr> {
match norm_util::analyze_action(alt) {
AlternativeAction::User(&ActionKind::User(_)) => {
AlternativeAction::User(&ActionKind::User(_)) |
AlternativeAction::User(&ActionKind::Fallible(_)) => {
return_err!(alt.span, "cannot infer types if there is custom action code");
}

View File

@ -79,7 +79,7 @@ impl<'grammar> Validator<'grammar> {
"multiple extern token definitions are not permitted");
}
let allowed_names = vec![intern(LOCATION)];
let allowed_names = vec![intern(LOCATION), intern(ERROR)];
let mut new_names = set();
for associated_type in &data.associated_types {
if !allowed_names.contains(&associated_type.type_name) {

View File

@ -110,11 +110,15 @@ rusty_peg! {
IF_COND: Condition =
("if" <c:COND>) => c;
ACTION: ActionKind = (LOOKAHEAD_ACTION / LOOKBEHIND_ACTION / USER_ACTION);
ACTION: ActionKind =
(LOOKAHEAD_ACTION / LOOKBEHIND_ACTION / FALLIBLE_USER_ACTION / USER_ACTION);
USER_ACTION: ActionKind =
("=>" <b:CODE>) => ActionKind::User(b);
FALLIBLE_USER_ACTION: ActionKind =
("=>?" <b:CODE>) => ActionKind::Fallible(b);
LOOKAHEAD_ACTION: ActionKind =
("=>@L") => ActionKind::Lookahead;