mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
Unify Errors so better error messages can be had.
This commit is contained in:
parent
bfde2c5238
commit
01e7ee59b7
23
src/ast.rs
23
src/ast.rs
@ -24,29 +24,6 @@ use std::cmp::PartialEq;
|
|||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
/// Encodes a parsing error with position information and a helpful description.
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct ParseError {
|
|
||||||
pub pos: Position,
|
|
||||||
pub description: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for ParseError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Parsing Error {} at line: {} column: {}",
|
|
||||||
self.description, self.pos.line, self.pos.column
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for ParseError {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
&self.description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! enum_type_equality {
|
macro_rules! enum_type_equality {
|
||||||
( $slf:ident, $r:expr, $( $l:pat ),* ) => {
|
( $slf:ident, $r:expr, $( $l:pat ),* ) => {
|
||||||
match $slf {
|
match $slf {
|
||||||
|
34
src/error.rs
34
src/error.rs
@ -18,6 +18,8 @@ use std::fmt;
|
|||||||
|
|
||||||
use ast::*;
|
use ast::*;
|
||||||
|
|
||||||
|
use nom;
|
||||||
|
|
||||||
/// ErrorType defines the various types of errors that can result from compiling UCG into an
|
/// ErrorType defines the various types of errors that can result from compiling UCG into an
|
||||||
/// output format.
|
/// output format.
|
||||||
pub enum ErrorType {
|
pub enum ErrorType {
|
||||||
@ -32,6 +34,7 @@ pub enum ErrorType {
|
|||||||
// Parsing Errors
|
// Parsing Errors
|
||||||
UnexpectedToken,
|
UnexpectedToken,
|
||||||
EmptyExpression,
|
EmptyExpression,
|
||||||
|
ParseError,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErrorType {
|
impl fmt::Display for ErrorType {
|
||||||
@ -46,6 +49,7 @@ impl fmt::Display for ErrorType {
|
|||||||
&ErrorType::FormatError => "FormatError",
|
&ErrorType::FormatError => "FormatError",
|
||||||
&ErrorType::UnexpectedToken => "UnexpectedToken",
|
&ErrorType::UnexpectedToken => "UnexpectedToken",
|
||||||
&ErrorType::EmptyExpression => "EmptyExpression",
|
&ErrorType::EmptyExpression => "EmptyExpression",
|
||||||
|
&ErrorType::ParseError => "ParseError",
|
||||||
};
|
};
|
||||||
w.write_str(name)
|
w.write_str(name)
|
||||||
}
|
}
|
||||||
@ -56,6 +60,7 @@ pub struct Error {
|
|||||||
pub err_type: ErrorType,
|
pub err_type: ErrorType,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
pub msg: String,
|
pub msg: String,
|
||||||
|
pub cause: Option<Box<Error>>,
|
||||||
_pkgonly: (),
|
_pkgonly: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,16 +70,41 @@ impl Error {
|
|||||||
err_type: t,
|
err_type: t,
|
||||||
pos: pos,
|
pos: pos,
|
||||||
msg: msg.into(),
|
msg: msg.into(),
|
||||||
|
cause: None,
|
||||||
_pkgonly: (),
|
_pkgonly: (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_with_cause<S: Into<String>>(
|
||||||
|
msg: S,
|
||||||
|
t: ErrorType,
|
||||||
|
pos: Position,
|
||||||
|
cause: Error,
|
||||||
|
) -> Self {
|
||||||
|
let mut e = Self::new(msg, t, pos);
|
||||||
|
e.cause = Some(Box::new(cause));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_errorkind<S: Into<String>>(
|
||||||
|
msg: S,
|
||||||
|
t: ErrorType,
|
||||||
|
pos: Position,
|
||||||
|
cause: nom::ErrorKind<Error>,
|
||||||
|
) -> Self {
|
||||||
|
match cause {
|
||||||
|
nom::ErrorKind::Custom(e) => Self::new_with_cause(msg, t, pos, e),
|
||||||
|
// TODO(jwall): We could get more creative here with our messaging.
|
||||||
|
_ => Self::new(msg, t, pos),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Error {
|
impl fmt::Debug for Error {
|
||||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}: \"{}\" {}:{}",
|
"{}: \"{}\" at line: {} column: {}",
|
||||||
self.err_type, self.msg, self.pos.line, self.pos.column
|
self.err_type, self.msg, self.pos.line, self.pos.column
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -84,7 +114,7 @@ impl fmt::Display for Error {
|
|||||||
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}: \"{}\" {}:{}",
|
"{}: \"{}\" at line: {} column: {}",
|
||||||
self.err_type, self.msg, self.pos.line, self.pos.column
|
self.err_type, self.msg, self.pos.line, self.pos.column
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
199
src/parse.rs
199
src/parse.rs
@ -23,10 +23,11 @@ use nom::IResult;
|
|||||||
|
|
||||||
use ast::*;
|
use ast::*;
|
||||||
use tokenizer::*;
|
use tokenizer::*;
|
||||||
|
use error;
|
||||||
|
|
||||||
type NomResult<'a, O> = nom::IResult<TokenIter<'a>, O, ParseError>;
|
type NomResult<'a, O> = nom::IResult<TokenIter<'a>, O, error::Error>;
|
||||||
|
|
||||||
type ParseResult<O> = Result<O, ParseError>;
|
type ParseResult<O> = Result<O, error::Error>;
|
||||||
|
|
||||||
fn symbol_to_value(s: &Token) -> ParseResult<Value> {
|
fn symbol_to_value(s: &Token) -> ParseResult<Value> {
|
||||||
Ok(Value::Symbol(value_node!(
|
Ok(Value::Symbol(value_node!(
|
||||||
@ -36,7 +37,7 @@ fn symbol_to_value(s: &Token) -> ParseResult<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// symbol is a bare unquoted field.
|
// symbol is a bare unquoted field.
|
||||||
named!(symbol<TokenIter, Value, ParseError>,
|
named!(symbol<TokenIter, Value, error::Error>,
|
||||||
match_type!(BAREWORD => symbol_to_value)
|
match_type!(BAREWORD => symbol_to_value)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ fn str_to_value(s: &Token) -> ParseResult<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// quoted_value is a quoted string.
|
// quoted_value is a quoted string.
|
||||||
named!(quoted_value<TokenIter, Value, ParseError>,
|
named!(quoted_value<TokenIter, Value, error::Error>,
|
||||||
match_type!(STR => str_to_value)
|
match_type!(STR => str_to_value)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -65,10 +66,11 @@ fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseRe
|
|||||||
let i = match FromStr::from_str(pref) {
|
let i = match FromStr::from_str(pref) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!("Not an integer! {}", pref),
|
format!("Not an integer! {}", pref),
|
||||||
pos: pref_pos,
|
error::ErrorType::UnexpectedToken,
|
||||||
})
|
pref_pos,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Ok(Value::Int(value_node!(i, pref_pos)));
|
return Ok(Value::Int(value_node!(i, pref_pos)));
|
||||||
@ -88,10 +90,11 @@ fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseRe
|
|||||||
let f = match FromStr::from_str(&to_parse) {
|
let f = match FromStr::from_str(&to_parse) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!("Not a float! {}", to_parse),
|
format!("Not a float! {}", to_parse),
|
||||||
pos: maybepos.unwrap(),
|
error::ErrorType::UnexpectedToken,
|
||||||
})
|
maybepos.unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Ok(Value::Float(value_node!(f, pref_pos)));
|
return Ok(Value::Float(value_node!(f, pref_pos)));
|
||||||
@ -109,7 +112,7 @@ fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseRe
|
|||||||
// *IMPORTANT*
|
// *IMPORTANT*
|
||||||
// It also means this combinator is risky when used with partial
|
// It also means this combinator is risky when used with partial
|
||||||
// inputs. So handle with care.
|
// inputs. So handle with care.
|
||||||
named!(number<TokenIter, Value, ParseError>,
|
named!(number<TokenIter, Value, error::Error>,
|
||||||
map_res!(alt!(
|
map_res!(alt!(
|
||||||
complete!(do_parse!( // 1.0
|
complete!(do_parse!( // 1.0
|
||||||
prefix: match_type!(DIGIT) >>
|
prefix: match_type!(DIGIT) >>
|
||||||
@ -138,7 +141,7 @@ named!(number<TokenIter, Value, ParseError>,
|
|||||||
);
|
);
|
||||||
// trace_macros!(false);
|
// trace_macros!(false);
|
||||||
|
|
||||||
named!(boolean_value<TokenIter, Value, ParseError>,
|
named!(boolean_value<TokenIter, Value, error::Error>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
b: match_type!(BOOLEAN) >>
|
b: match_type!(BOOLEAN) >>
|
||||||
(Value::Boolean(Positioned{
|
(Value::Boolean(Positioned{
|
||||||
@ -149,7 +152,7 @@ named!(boolean_value<TokenIter, Value, ParseError>,
|
|||||||
);
|
);
|
||||||
|
|
||||||
named!(
|
named!(
|
||||||
field_value<TokenIter, (Token, Expression), ParseError>,
|
field_value<TokenIter, (Token, Expression), error::Error>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
field: match_type!(BAREWORD) >>
|
field: match_type!(BAREWORD) >>
|
||||||
punct!("=") >>
|
punct!("=") >>
|
||||||
@ -167,13 +170,13 @@ fn vec_to_tuple(t: (Position, Option<FieldList>)) -> ParseResult<Value> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(field_list<TokenIter, FieldList, ParseError>,
|
named!(field_list<TokenIter, FieldList, error::Error>,
|
||||||
separated_list!(punct!(","), field_value)
|
separated_list!(punct!(","), field_value)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(
|
named!(
|
||||||
#[doc="Capture a tuple of named fields with values. {<field>=<value>,...}"],
|
#[doc="Capture a tuple of named fields with values. {<field>=<value>,...}"],
|
||||||
tuple<TokenIter, Value, ParseError>,
|
tuple<TokenIter, Value, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
pos: pos >>
|
pos: pos >>
|
||||||
@ -193,7 +196,7 @@ fn tuple_to_list<Sp: Into<Position>>(t: (Sp, Vec<Expression>)) -> ParseResult<Va
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(list_value<TokenIter, Value, ParseError>,
|
named!(list_value<TokenIter, Value, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
start: punct!("[") >>
|
start: punct!("[") >>
|
||||||
@ -205,7 +208,7 @@ named!(list_value<TokenIter, Value, ParseError>,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(empty_value<TokenIter, Value, ParseError>,
|
named!(empty_value<TokenIter, Value, error::Error>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
pos: pos >>
|
pos: pos >>
|
||||||
match_type!(EMPTY) >>
|
match_type!(EMPTY) >>
|
||||||
@ -213,7 +216,7 @@ named!(empty_value<TokenIter, Value, ParseError>,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(value<TokenIter, Value, ParseError>,
|
named!(value<TokenIter, Value, error::Error>,
|
||||||
alt!(
|
alt!(
|
||||||
boolean_value |
|
boolean_value |
|
||||||
empty_value |
|
empty_value |
|
||||||
@ -228,7 +231,7 @@ fn value_to_expression(v: Value) -> ParseResult<Expression> {
|
|||||||
Ok(Expression::Simple(v))
|
Ok(Expression::Simple(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(simple_expression<TokenIter, Expression, ParseError>,
|
named!(simple_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
value,
|
value,
|
||||||
value_to_expression
|
value_to_expression
|
||||||
@ -266,20 +269,20 @@ macro_rules! do_binary_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// trace_macros!(true);
|
// trace_macros!(true);
|
||||||
named!(add_expression<TokenIter, Expression, ParseError>,
|
named!(add_expression<TokenIter, Expression, error::Error>,
|
||||||
do_binary_expr!(punct!("+"), BinaryExprType::Add)
|
do_binary_expr!(punct!("+"), BinaryExprType::Add)
|
||||||
);
|
);
|
||||||
// trace_macros!(false);
|
// trace_macros!(false);
|
||||||
|
|
||||||
named!(sub_expression<TokenIter, Expression, ParseError>,
|
named!(sub_expression<TokenIter, Expression, error::Error>,
|
||||||
do_binary_expr!(punct!("-"), BinaryExprType::Sub)
|
do_binary_expr!(punct!("-"), BinaryExprType::Sub)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(mul_expression<TokenIter, Expression, ParseError>,
|
named!(mul_expression<TokenIter, Expression, error::Error>,
|
||||||
do_binary_expr!(punct!("*"), BinaryExprType::Mul)
|
do_binary_expr!(punct!("*"), BinaryExprType::Mul)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(div_expression<TokenIter, Expression, ParseError>,
|
named!(div_expression<TokenIter, Expression, error::Error>,
|
||||||
do_binary_expr!(punct!("/"), BinaryExprType::Div)
|
do_binary_expr!(punct!("/"), BinaryExprType::Div)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -287,7 +290,7 @@ fn expression_to_grouped_expression(e: Expression) -> ParseResult<Expression> {
|
|||||||
Ok(Expression::Grouped(Box::new(e)))
|
Ok(Expression::Grouped(Box::new(e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(grouped_expression<TokenIter, Expression, ParseError>,
|
named!(grouped_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
preceded!(punct!("("), terminated!(expression, punct!(")"))),
|
preceded!(punct!("("), terminated!(expression, punct!(")"))),
|
||||||
expression_to_grouped_expression
|
expression_to_grouped_expression
|
||||||
@ -346,10 +349,11 @@ fn selector_list(input: TokenIter) -> NomResult<SelectorList> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
return IResult::Error(nom::ErrorKind::Custom(ParseError {
|
return IResult::Error(nom::ErrorKind::Custom(error::Error::new(
|
||||||
description: "(.) with no selector fields after".to_string(),
|
"(.) with no selector fields after".to_string(),
|
||||||
pos: is_dot.unwrap().pos,
|
error::ErrorType::IncompleteParsing,
|
||||||
}));
|
is_dot.unwrap().pos,
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
(rest, Some(list))
|
(rest, Some(list))
|
||||||
}
|
}
|
||||||
@ -374,7 +378,7 @@ fn tuple_to_copy(t: (SelectorDef, FieldList)) -> ParseResult<Expression> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(copy_expression<TokenIter, Expression, ParseError>,
|
named!(copy_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
pos: pos >>
|
pos: pos >>
|
||||||
@ -402,16 +406,17 @@ fn tuple_to_macro(mut t: (Position, Vec<Value>, Value)) -> ParseResult<Expressio
|
|||||||
pos: t.0,
|
pos: t.0,
|
||||||
})),
|
})),
|
||||||
// TODO(jwall): Show a better version of the unexpected parsed value.
|
// TODO(jwall): Show a better version of the unexpected parsed value.
|
||||||
val => Err(ParseError {
|
val => Err(error::Error::new(
|
||||||
description: format!("Expected Tuple Got {:?}", val),
|
format!("Expected Tuple Got {:?}", val),
|
||||||
pos: t.0,
|
error::ErrorType::UnexpectedToken,
|
||||||
}),
|
t.0,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(arglist<TokenIter, Vec<Value>, ParseError>, separated_list!(punct!(","), symbol));
|
named!(arglist<TokenIter, Vec<Value>, error::Error>, separated_list!(punct!(","), symbol));
|
||||||
|
|
||||||
named!(macro_expression<TokenIter, Expression, ParseError>,
|
named!(macro_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
pos: pos >>
|
pos: pos >>
|
||||||
@ -435,14 +440,15 @@ fn tuple_to_select(t: (Position, Expression, Expression, Value)) -> ParseResult<
|
|||||||
tuple: v.val,
|
tuple: v.val,
|
||||||
pos: t.0,
|
pos: t.0,
|
||||||
})),
|
})),
|
||||||
val => Err(ParseError {
|
val => Err(error::Error::new(
|
||||||
description: format!("Expected Tuple Got {:?}", val),
|
format!("Expected Tuple Got {:?}", val),
|
||||||
pos: t.0,
|
error::ErrorType::UnexpectedToken,
|
||||||
}),
|
t.0,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(select_expression<TokenIter, Expression, ParseError>,
|
named!(select_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
start: word!("select") >>
|
start: word!("select") >>
|
||||||
@ -463,7 +469,7 @@ fn tuple_to_format(t: (Token, Vec<Expression>)) -> ParseResult<Expression> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(format_expression<TokenIter, Expression, ParseError>,
|
named!(format_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
tmpl: match_type!(STR) >>
|
tmpl: match_type!(STR) >>
|
||||||
@ -485,10 +491,11 @@ fn tuple_to_call(t: (Position, Value, Vec<Expression>)) -> ParseResult<Expressio
|
|||||||
pos: Position::new(t.0.line as usize, t.0.column as usize),
|
pos: Position::new(t.0.line as usize, t.0.column as usize),
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Err(ParseError {
|
Err(error::Error::new(
|
||||||
description: format!("Expected Selector Got {:?}", t.0),
|
format!("Expected Selector Got {:?}", t.0),
|
||||||
pos: Position::new(t.0.line as usize, t.0.column as usize),
|
error::ErrorType::UnexpectedToken,
|
||||||
})
|
Position::new(t.0.line as usize, t.0.column as usize),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +507,7 @@ fn vec_to_selector_value(t: (Position, SelectorList)) -> ParseResult<Value> {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(selector_value<TokenIter, Value, ParseError>,
|
named!(selector_value<TokenIter, Value, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
sl: selector_list >>
|
sl: selector_list >>
|
||||||
@ -510,7 +517,7 @@ named!(selector_value<TokenIter, Value, ParseError>,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(call_expression<TokenIter, Expression, ParseError>,
|
named!(call_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
macroname: selector_value >>
|
macroname: selector_value >>
|
||||||
@ -557,13 +564,14 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
|||||||
} else if &tpl.1.fragment == "filter" {
|
} else if &tpl.1.fragment == "filter" {
|
||||||
ListOpType::Filter
|
ListOpType::Filter
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!(
|
format!(
|
||||||
"Expected one of 'map' or 'filter' but got '{}'",
|
"Expected one of 'map' or 'filter' but got '{}'",
|
||||||
tpl.1.fragment
|
tpl.1.fragment
|
||||||
),
|
),
|
||||||
pos: pos,
|
error::ErrorType::UnexpectedToken,
|
||||||
});
|
pos,
|
||||||
|
));
|
||||||
};
|
};
|
||||||
let macroname = tpl.2;
|
let macroname = tpl.2;
|
||||||
let list = tpl.3;
|
let list = tpl.3;
|
||||||
@ -572,17 +580,19 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
|||||||
// two sections.
|
// two sections.
|
||||||
let fieldname: String = match &mut def.sel.tail {
|
let fieldname: String = match &mut def.sel.tail {
|
||||||
&mut None => {
|
&mut None => {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!("Missing a result field for the macro"),
|
format!("Missing a result field for the macro"),
|
||||||
pos: pos,
|
error::ErrorType::IncompleteParsing,
|
||||||
});
|
pos,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
&mut Some(ref mut tl) => {
|
&mut Some(ref mut tl) => {
|
||||||
if tl.len() < 1 {
|
if tl.len() < 1 {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!("Missing a result field for the macro"),
|
format!("Missing a result field for the macro"),
|
||||||
pos: def.pos.clone(),
|
error::ErrorType::IncompleteParsing,
|
||||||
});
|
def.pos.clone(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let fname = tl.pop();
|
let fname = tl.pop();
|
||||||
fname.unwrap().fragment
|
fname.unwrap().fragment
|
||||||
@ -598,18 +608,20 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
// TODO(jwall): We should print a pretter message than debug formatting here.
|
// TODO(jwall): We should print a pretter message than debug formatting here.
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
pos: pos,
|
format!("Expected a list but got {:?}", list),
|
||||||
description: format!("Expected a list but got {:?}", list),
|
error::ErrorType::UnexpectedToken,
|
||||||
});
|
pos,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
pos: pos,
|
format!("Expected a selector but got {:?}", macroname),
|
||||||
description: format!("Expected a macro but got {:?}", macroname),
|
error::ErrorType::UnexpectedToken,
|
||||||
});
|
pos,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(list_op_expression<TokenIter, Expression, ParseError>,
|
named!(list_op_expression<TokenIter, Expression, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
pos: pos >>
|
pos: pos >>
|
||||||
@ -632,7 +644,7 @@ named!(list_op_expression<TokenIter, Expression, ParseError>,
|
|||||||
// *IMPORTANT*
|
// *IMPORTANT*
|
||||||
// It also means this combinator is risky when used with partial
|
// It also means this combinator is risky when used with partial
|
||||||
// inputs. So handle with care.
|
// inputs. So handle with care.
|
||||||
named!(expression<TokenIter, Expression, ParseError>,
|
named!(expression<TokenIter, Expression, error::Error>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
expr: alt!(
|
expr: alt!(
|
||||||
complete!(list_op_expression) |
|
complete!(list_op_expression) |
|
||||||
@ -656,7 +668,7 @@ fn expression_to_statement(v: Expression) -> ParseResult<Statement> {
|
|||||||
Ok(Statement::Expression(v))
|
Ok(Statement::Expression(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(expression_statement<TokenIter, Statement, ParseError>,
|
named!(expression_statement<TokenIter, Statement, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
terminated!(expression, punct!(";")),
|
terminated!(expression, punct!(";")),
|
||||||
expression_to_statement
|
expression_to_statement
|
||||||
@ -670,7 +682,7 @@ fn tuple_to_let(t: (Token, Expression)) -> ParseResult<Statement> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(let_statement<TokenIter, Statement, ParseError>,
|
named!(let_statement<TokenIter, Statement, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
word!("let") >>
|
word!("let") >>
|
||||||
@ -691,7 +703,7 @@ fn tuple_to_import(t: (Token, Token)) -> ParseResult<Statement> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
named!(import_statement<TokenIter, Statement, ParseError>,
|
named!(import_statement<TokenIter, Statement, error::Error>,
|
||||||
map_res!(
|
map_res!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
word!("import") >>
|
word!("import") >>
|
||||||
@ -705,7 +717,7 @@ named!(import_statement<TokenIter, Statement, ParseError>,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(statement<TokenIter, Statement, ParseError>,
|
named!(statement<TokenIter, Statement, error::Error>,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
stmt: alt_complete!(
|
stmt: alt_complete!(
|
||||||
import_statement |
|
import_statement |
|
||||||
@ -716,8 +728,8 @@ named!(statement<TokenIter, Statement, ParseError>,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Parses a LocatedSpan into a list of Statements or a ParseError.
|
/// Parses a LocatedSpan into a list of Statements or an error::Error.
|
||||||
pub fn parse(input: LocatedSpan<&str>) -> Result<Vec<Statement>, ParseError> {
|
pub fn parse(input: LocatedSpan<&str>) -> Result<Vec<Statement>, error::Error> {
|
||||||
match tokenize(input) {
|
match tokenize(input) {
|
||||||
Ok(tokenized) => {
|
Ok(tokenized) => {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -734,25 +746,25 @@ pub fn parse(input: LocatedSpan<&str>) -> Result<Vec<Statement>, ParseError> {
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
IResult::Error(e) => {
|
IResult::Error(e) => {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new_with_errorkind(
|
||||||
description: format!(
|
format!("Statement Parse error: {:?} current token: {:?}", e, i_[0]),
|
||||||
"Statement Parse error: {:?} current token: {:?}",
|
error::ErrorType::ParseError,
|
||||||
e, i_[0]
|
Position {
|
||||||
),
|
|
||||||
pos: Position {
|
|
||||||
line: i_[0].pos.line,
|
line: i_[0].pos.line,
|
||||||
column: i_[0].pos.column,
|
column: i_[0].pos.column,
|
||||||
},
|
},
|
||||||
});
|
e,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
IResult::Incomplete(ei) => {
|
IResult::Incomplete(ei) => {
|
||||||
return Err(ParseError {
|
return Err(error::Error::new(
|
||||||
description: format!("Unexpected end of parsing input: {:?}", ei),
|
format!("Unexpected end of parsing input: {:?}", ei),
|
||||||
pos: Position {
|
error::ErrorType::IncompleteParsing,
|
||||||
|
Position {
|
||||||
line: i_[0].pos.line,
|
line: i_[0].pos.line,
|
||||||
column: i_[0].pos.column,
|
column: i_[0].pos.column,
|
||||||
},
|
},
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
IResult::Done(rest, stmt) => {
|
IResult::Done(rest, stmt) => {
|
||||||
out.push(stmt);
|
out.push(stmt);
|
||||||
@ -766,12 +778,11 @@ pub fn parse(input: LocatedSpan<&str>) -> Result<Vec<Statement>, ParseError> {
|
|||||||
return Ok(out);
|
return Ok(out);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// FIXME(jwall): We should really capture the location
|
return Err(error::Error::new(
|
||||||
// of the tokenization error here.
|
format!("Tokenization Error {:?}", e.1),
|
||||||
return Err(ParseError {
|
error::ErrorType::ParseError,
|
||||||
description: format!("Tokenize Error: {:?}", e.1),
|
e.0,
|
||||||
pos: e.0,
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ use nom;
|
|||||||
use nom::{alpha, digit, is_alphanumeric, multispace};
|
use nom::{alpha, digit, is_alphanumeric, multispace};
|
||||||
use nom::{InputIter, InputLength, Slice};
|
use nom::{InputIter, InputLength, Slice};
|
||||||
use ast::*;
|
use ast::*;
|
||||||
|
use error;
|
||||||
use std;
|
use std;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
@ -327,8 +328,6 @@ named!(token( Span ) -> Token,
|
|||||||
end_of_input)
|
end_of_input)
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO(jwall): This should return a ParseError instead.
|
|
||||||
|
|
||||||
/// Consumes an input Span and returns either a Vec<Token> or a nom::ErrorKind.
|
/// Consumes an input Span and returns either a Vec<Token> or a nom::ErrorKind.
|
||||||
pub fn tokenize(input: Span) -> Result<Vec<Token>, (Position, nom::ErrorKind)> {
|
pub fn tokenize(input: Span) -> Result<Vec<Token>, (Position, nom::ErrorKind)> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -378,7 +377,7 @@ pub fn tokenize(input: Span) -> Result<Vec<Token>, (Position, nom::ErrorKind)> {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn token_clone(t: &Token) -> Result<Token, ParseError> {
|
pub fn token_clone(t: &Token) -> Result<Token, error::Error> {
|
||||||
Ok(t.clone())
|
Ok(t.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,10 +447,10 @@ macro_rules! match_type {
|
|||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
if i_.input_len() == 0 {
|
if i_.input_len() == 0 {
|
||||||
nom::IResult::Error(
|
nom::IResult::Error(
|
||||||
nom::ErrorKind::Custom(ParseError{
|
nom::ErrorKind::Custom(error::Error::new(
|
||||||
description: format!("End of Input! {}", $msg),
|
format!("End of Input! {}", $msg),
|
||||||
pos: Position{line: 0, column: 0}
|
error::ErrorType::IncompleteParsing,
|
||||||
}))
|
Position{line: 0, column: 0})))
|
||||||
} else {
|
} else {
|
||||||
let tok = &(i_[0]);
|
let tok = &(i_[0]);
|
||||||
if tok.typ == $t {
|
if tok.typ == $t {
|
||||||
@ -461,9 +460,10 @@ macro_rules! match_type {
|
|||||||
nom::ErrorKind::Custom(e.into())),
|
nom::ErrorKind::Custom(e.into())),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nom::IResult::Error(nom::ErrorKind::Custom(ParseError{
|
nom::IResult::Error(nom::ErrorKind::Custom(error::Error::new(
|
||||||
description: $msg.to_string(),
|
$msg.to_string(),
|
||||||
pos: tok.pos.clone()}))
|
error::ErrorType::UnexpectedToken,
|
||||||
|
tok.pos.clone())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -502,9 +502,10 @@ macro_rules! match_token {
|
|||||||
nom::ErrorKind::Custom(e.into())),
|
nom::ErrorKind::Custom(e.into())),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nom::IResult::Error(nom::ErrorKind::Custom(ParseError{
|
nom::IResult::Error(nom::ErrorKind::Custom(error::Error::new(
|
||||||
description: format!("{} Instead is ({})", $msg, tok.fragment),
|
format!("{} Instead is ({})", $msg, tok.fragment),
|
||||||
pos: tok.pos.clone()}))
|
error::ErrorType::UnexpectedToken,
|
||||||
|
tok.pos.clone())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -525,7 +526,7 @@ macro_rules! word {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// pos gets the current position from a TokenIter input without consuming it.
|
/// pos gets the current position from a TokenIter input without consuming it.
|
||||||
pub fn pos(i: TokenIter) -> nom::IResult<TokenIter, Position, ParseError> {
|
pub fn pos(i: TokenIter) -> nom::IResult<TokenIter, Position, error::Error> {
|
||||||
let tok = &i[0];
|
let tok = &i[0];
|
||||||
let line = tok.pos.line;
|
let line = tok.pos.line;
|
||||||
let column = tok.pos.column;
|
let column = tok.pos.column;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user