1use std::fmt;
2use tokens::TokenValue;
3use error::{ Error, ExtensionError, At, Location };
4
5#[derive(Clone, Debug)]
6pub enum Received {
7 Token(TokenValue),
8 EndOfStream,
9}
10
11#[derive(Clone, Debug)]
12pub enum TemplateError {
13 UnexpectedEndOfTemplate,
14 ExpectedTokenTypeButReceived((TokenValue, Received)),
15 UnexpectedTokenValue(TokenValue),
16 ExpectedOtherTokenValue((TokenValue, TokenValue)),
17 ExpectedArrayElement,
18 ArrayValueMustBeFollowedByComma,
19 ArrayNotClosed,
20 ExpectedHashElement,
21 HashValueMustBeFollowedByComma,
22 InvalidHashKey { unexpected: TokenValue },
23 HashKeyMustBeFollowedByColon,
24 HashNotClosed,
25 ExpectedNameOrNumber,
26 ListOfArgumentsMustBeginWithParenthesis,
27 ArgumentsMustBeSeparatedByComma,
28 ListOfArgumentsMustCloseWithParenthesis,
29 Unclosed(String),
30 UnclosedComment,
31 UnclosedBlock(String),
32 Unexpected(String),
33 UnexpectedCharacter(String),
34 ParenthesisNotClosed,
35 MustStartWithTagName,
36 DefaultValueForArgumentMustBeConstant,
37 ParameterNameMustBeAString { given: String },
38 TemplateNotFound(String),
39 CustomError(Box<ExtensionError>),
40}
41
42impl TemplateError {
43 pub fn at(self, line: usize) -> At<TemplateError> {
44 At::new(self, Location::new(line))
45 }
46}
47
48impl fmt::Display for TemplateError {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 match *self {
51 TemplateError::UnexpectedEndOfTemplate => write!(f, "Unexpected end of template"),
52 TemplateError::ExpectedTokenTypeButReceived((ref token, ref received)) => {
53 let (english_name, _) = token.get_english();
54 match *received {
55 Received::EndOfStream => write!(f, "Expected token \"{}\" but received the end of stream", english_name),
56 Received::Token(ref other) => {
57 let (other_english_name, value) = other.get_english();
58 match value {
59 Some(value) => write!(f, "Expected \"{}\" but received \"{}\" with value {:?}", english_name, other_english_name, value),
60 None => write!(f, "Expected \"{}\" but received \"{}\"", english_name, other_english_name),
61 }
62 },
63 }
64 },
65 TemplateError::ExpectedOtherTokenValue((ref token, ref other)) => {
66 let unexpected_message = format!("{}", TemplateError::UnexpectedTokenValue(token.clone()));
67 let (other_english_name, other_value) = other.get_english();
68 match other_value {
69 Some(value) => write!(f, "{} (\"{}\" expected with value {:?})", unexpected_message, other_english_name, value),
70 None => write!(f, "{} (\"{}\" expected)", unexpected_message, other_english_name),
71 }
72 },
73 TemplateError::ExpectedArrayElement => write!(f, "An array element was expected"),
74 TemplateError::ArrayValueMustBeFollowedByComma => write!(f, "An array element must be followed by a comma"),
75 TemplateError::ArrayNotClosed => write!(f, "An opened array is not properly closed"),
76 TemplateError::ExpectedHashElement => write!(f, "A hash element was expected"),
77 TemplateError::HashValueMustBeFollowedByComma => write!(f, "A hash value must be followed by a comma"),
78 TemplateError::InvalidHashKey { ref unexpected } => {
79 let (english_name, value) = unexpected.get_english();
80 match value {
81 Some(value) => write!(f, "A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses: unexpected token \"{}\" of value {:?}", english_name, value),
82 None => write!(f, "A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses: unexpected token \"{}\"", english_name),
83 }
84 },
85 TemplateError::HashKeyMustBeFollowedByColon => write!(f, "A hash key must be followed by a colon (:)"),
86 TemplateError::HashNotClosed => write!(f, "An opened hash is not properly closed"),
87 TemplateError::ExpectedNameOrNumber => write!(f, "Expected name or number"),
88 TemplateError::ListOfArgumentsMustBeginWithParenthesis => write!(f, "A list of arguments must begin with an opening parenthesis"),
89 TemplateError::ArgumentsMustBeSeparatedByComma => write!(f, "Arguments must be separated by a comma"),
90 TemplateError::ListOfArgumentsMustCloseWithParenthesis => write!(f, "A list of arguments must be closed by a parenthesis"),
91 TemplateError::UnexpectedTokenValue(ref token) => {
92 let (english_name, value) = token.get_english();
93 match value {
94 Some(value) => write!(f, "Unexpected token \"{}\" of value {:?}", english_name, value),
95 None => write!(f, "Unexpected token \"{}\"", english_name),
96 }
97 },
98 TemplateError::Unclosed(ref s) => write!(f, "Unclosed \"{}\"", s),
99 TemplateError::UnclosedComment => write!(f, "Unclosed comment"),
100 TemplateError::UnclosedBlock(ref s) => write!(f, "Unexpected end of file: Unclosed \"{}\" block", s),
101 TemplateError::Unexpected(ref s) => write!(f, "Unexpected \"{}\"", s),
102 TemplateError::UnexpectedCharacter(ref s) => write!(f, "Unexpected character \"{}\"", s),
103 TemplateError::ParenthesisNotClosed => write!(f, "An opened parenthesis is not properly closed"),
104 TemplateError::MustStartWithTagName => write!(f, "A block must start with a tag name"),
105 TemplateError::DefaultValueForArgumentMustBeConstant => write!(f, "A default value for an argument must be a constant (a boolean, a string, a number, or an array)."),
106 TemplateError::ParameterNameMustBeAString { ref given } => write!(f, "A parameter name must be a string, \"{}\" given", given),
107 TemplateError::TemplateNotFound(ref name) => write!(f, "Template \"{}\" was not found", name),
108 TemplateError::CustomError(ref e) => write!(f, "{}", e),
109 }
110 }
111}
112
113impl From<At<TemplateError>> for Error {
114 fn from(inner: At<TemplateError>) -> Error {
115 Error::Template(inner)
116 }
117}