Improve syntax error messages; Add test
This commit is contained in:
parent
3ca7aa077b
commit
6bab3db5e5
@ -16,6 +16,7 @@ pub enum Error {
|
|||||||
expected: &'static str,
|
expected: &'static str,
|
||||||
actual: &'static str,
|
actual: &'static str,
|
||||||
location: tree_sitter::Point,
|
location: tree_sitter::Point,
|
||||||
|
surrounding_text: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
ExpectedFieldName,
|
ExpectedFieldName,
|
||||||
@ -530,9 +531,11 @@ impl fmt::Display for Error {
|
|||||||
expected,
|
expected,
|
||||||
actual,
|
actual,
|
||||||
location,
|
location,
|
||||||
|
surrounding_text,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Unexpected syntax at {location}. Expected {expected}, but found {actual}."
|
"Unexpected syntax at {location}. Expected {expected}, but found {actual}.
|
||||||
|
>> {surrounding_text} <<"
|
||||||
),
|
),
|
||||||
ExpectedFieldName => write!(
|
ExpectedFieldName => write!(
|
||||||
f,
|
f,
|
||||||
|
@ -136,8 +136,6 @@ pub enum Item {
|
|||||||
|
|
||||||
impl EvaluatorTree for Item {
|
impl EvaluatorTree for Item {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
debug_assert_eq!(node.kind(), "item");
|
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
if child.kind() == "comment" {
|
if child.kind() == "comment" {
|
||||||
@ -152,6 +150,7 @@ impl EvaluatorTree for Item {
|
|||||||
expected: "comment or statement",
|
expected: "comment or statement",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
|
surrounding_text: source[node.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,8 +177,6 @@ pub enum Statement {
|
|||||||
|
|
||||||
impl EvaluatorTree for Statement {
|
impl EvaluatorTree for Statement {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
debug_assert_eq!(node.kind(), "statement");
|
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
@ -196,6 +193,7 @@ impl EvaluatorTree for Statement {
|
|||||||
expected: "expression",
|
expected: "expression",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
|
surrounding_text: source[node.byte_range()].to_string(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,8 +217,6 @@ pub enum Expression {
|
|||||||
|
|
||||||
impl EvaluatorTree for Expression {
|
impl EvaluatorTree for Expression {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
debug_assert_eq!(node.kind(), "expression");
|
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
let expression = match child.kind() {
|
let expression = match child.kind() {
|
||||||
@ -235,6 +231,7 @@ impl EvaluatorTree for Expression {
|
|||||||
"identifier, operation, control_flow, assignment, math, function_call or value",
|
"identifier, operation, control_flow, assignment, math, function_call or value",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
|
surrounding_text: source[node.byte_range()].to_string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,8 +267,6 @@ impl Identifier {
|
|||||||
|
|
||||||
impl EvaluatorTree for Identifier {
|
impl EvaluatorTree for Identifier {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "identifier");
|
|
||||||
|
|
||||||
let identifier = &source[node.byte_range()];
|
let identifier = &source[node.byte_range()];
|
||||||
|
|
||||||
Ok(Identifier(identifier.to_string()))
|
Ok(Identifier(identifier.to_string()))
|
||||||
@ -293,8 +288,6 @@ pub struct ControlFlow {
|
|||||||
|
|
||||||
impl EvaluatorTree for ControlFlow {
|
impl EvaluatorTree for ControlFlow {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "control_flow");
|
|
||||||
|
|
||||||
let if_node = node.child(1).unwrap();
|
let if_node = node.child(1).unwrap();
|
||||||
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
||||||
|
|
||||||
@ -336,8 +329,6 @@ pub struct Assignment {
|
|||||||
|
|
||||||
impl EvaluatorTree for Assignment {
|
impl EvaluatorTree for Assignment {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "assignment");
|
|
||||||
|
|
||||||
let identifier_node = node.child(0).unwrap();
|
let identifier_node = node.child(0).unwrap();
|
||||||
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||||
|
|
||||||
@ -369,8 +360,6 @@ pub struct Math {
|
|||||||
|
|
||||||
impl EvaluatorTree for Math {
|
impl EvaluatorTree for Math {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "math");
|
|
||||||
|
|
||||||
let left_node = node.child(0).unwrap();
|
let left_node = node.child(0).unwrap();
|
||||||
let left = Expression::from_syntax_node(left_node, source)?;
|
let left = Expression::from_syntax_node(left_node, source)?;
|
||||||
|
|
||||||
@ -386,6 +375,7 @@ impl EvaluatorTree for Math {
|
|||||||
expected: "+, -, *, / or %",
|
expected: "+, -, *, / or %",
|
||||||
actual: operator_node.kind(),
|
actual: operator_node.kind(),
|
||||||
location: operator_node.start_position(),
|
location: operator_node.start_position(),
|
||||||
|
surrounding_text: source[operator_node.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -432,8 +422,6 @@ pub struct FunctionCall {
|
|||||||
|
|
||||||
impl EvaluatorTree for FunctionCall {
|
impl EvaluatorTree for FunctionCall {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "function_call");
|
|
||||||
|
|
||||||
let identifier_node = node.child(0).unwrap();
|
let identifier_node = node.child(0).unwrap();
|
||||||
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||||
|
|
||||||
@ -585,6 +573,27 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn evaluate_if_else_if_then_else() {
|
||||||
|
assert_eq!(
|
||||||
|
evaluate(
|
||||||
|
"
|
||||||
|
if false
|
||||||
|
then 'no'
|
||||||
|
else if 1 + 1 = 3
|
||||||
|
then 'nope'
|
||||||
|
else
|
||||||
|
'ok'
|
||||||
|
"
|
||||||
|
),
|
||||||
|
vec![Ok(Value::String("ok".to_string()))]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
evaluate("if true then 1.0 else 42.0"),
|
||||||
|
vec![Ok(Value::Float(1.0))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_function() {
|
fn evaluate_function() {
|
||||||
let function = Function::new(
|
let function = Function::new(
|
||||||
|
@ -49,8 +49,6 @@ pub enum Value {
|
|||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
debug_assert_eq!(node.kind(), "value");
|
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
@ -185,13 +183,12 @@ impl Value {
|
|||||||
expected: "string, integer, float, boolean, list, table, map, function or empty",
|
expected: "string, integer, float, boolean, list, table, map, function or empty",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
|
surrounding_text: source[child.byte_range()].to_string(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
debug_assert_eq!(node.kind(), "list");
|
|
||||||
|
|
||||||
let item_count = node.named_child_count();
|
let item_count = node.named_child_count();
|
||||||
let mut values = Vec::with_capacity(item_count);
|
let mut values = Vec::with_capacity(item_count);
|
||||||
let mut current_node = node.child(1).unwrap();
|
let mut current_node = node.child(1).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user