Implement tables
This commit is contained in:
parent
a42b43ed78
commit
5551f40ffd
133
src/interface.rs
133
src/interface.rs
@ -5,7 +5,7 @@
|
|||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::{Parser, Tree as TSTree, TreeCursor};
|
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
||||||
|
|
||||||
use crate::{language, Error, Primitive, Result, Value, VariableMap};
|
use crate::{language, Error, Primitive, Result, Value, VariableMap};
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ pub trait EvaluatorTree: Sized {
|
|||||||
///
|
///
|
||||||
/// If necessary, the source code can be accessed directly by getting the
|
/// If necessary, the source code can be accessed directly by getting the
|
||||||
/// node's byte range.
|
/// node's byte range.
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self>;
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self>;
|
||||||
|
|
||||||
/// Execute dust code by traversing the tree
|
/// Execute dust code by traversing the tree
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value>;
|
fn run(&self, context: &mut VariableMap) -> Result<Value>;
|
||||||
@ -109,10 +109,8 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
|
|
||||||
assert_eq!(cursor_0.node().kind(), "root");
|
assert_eq!(cursor_0.node().kind(), "root");
|
||||||
|
|
||||||
cursor_1.goto_first_child();
|
for item_node in node.children(&mut cursor_0) {
|
||||||
|
let item_result = Item::from_syntax_node(item_node, self.source);
|
||||||
for _ in node.children(&mut cursor_0) {
|
|
||||||
let item_result = Item::new(self.source, &mut cursor_1);
|
|
||||||
|
|
||||||
match item_result {
|
match item_result {
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
@ -140,12 +138,10 @@ pub enum Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Item {
|
impl EvaluatorTree for Item {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
debug_assert_eq!(node.kind(), "item");
|
||||||
cursor.goto_first_child();
|
|
||||||
let child = cursor.node();
|
|
||||||
|
|
||||||
assert_eq!(node.kind(), "item");
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
if child.kind() == "comment" {
|
if child.kind() == "comment" {
|
||||||
let byte_range = child.byte_range();
|
let byte_range = child.byte_range();
|
||||||
@ -153,7 +149,7 @@ impl EvaluatorTree for Item {
|
|||||||
|
|
||||||
Ok(Item::Comment(comment_text.to_string()))
|
Ok(Item::Comment(comment_text.to_string()))
|
||||||
} else if child.kind() == "statement" {
|
} else if child.kind() == "statement" {
|
||||||
Ok(Item::Statement(Statement::new(source, cursor)?))
|
Ok(Item::Statement(Statement::from_syntax_node(child, source)?))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedSyntax {
|
Err(Error::UnexpectedSyntax {
|
||||||
expected: "comment or statement",
|
expected: "comment or statement",
|
||||||
@ -182,12 +178,15 @@ pub enum Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Statement {
|
impl EvaluatorTree for Statement {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
cursor.goto_first_child();
|
debug_assert_eq!(node.kind(), "statement");
|
||||||
let child = cursor.node();
|
|
||||||
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"expression" => Ok(Self::Expression(Expression::new(source, cursor)?)),
|
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
||||||
|
child, source,
|
||||||
|
)?)),
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
expected: "expression",
|
expected: "expression",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
@ -214,20 +213,24 @@ pub enum Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Expression {
|
impl EvaluatorTree for Expression {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
debug_assert_eq!(node.kind(), "expression");
|
||||||
cursor.goto_first_child();
|
|
||||||
let child = cursor.node();
|
|
||||||
|
|
||||||
assert_eq!(node.kind(), "expression");
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
let expression = match child.kind() {
|
let expression = match child.kind() {
|
||||||
"identifier" => Self::Identifier(Identifier::new(source, cursor)?),
|
"identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?),
|
||||||
"value" => Expression::Value(Value::from_source(source, cursor)?),
|
"value" => Expression::Value(Value::from_syntax_node(child, source)?),
|
||||||
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)),
|
"control_flow" => {
|
||||||
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)),
|
Expression::ControlFlow(Box::new(ControlFlow::from_syntax_node(child, source)?))
|
||||||
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)),
|
}
|
||||||
"function_call" => Expression::FunctionCall(FunctionCall::new(source, cursor)?),
|
"assignment" => {
|
||||||
|
Expression::Assignment(Box::new(Assignment::from_syntax_node(child, source)?))
|
||||||
|
}
|
||||||
|
"math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)),
|
||||||
|
"function_call" => {
|
||||||
|
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
|
||||||
|
}
|
||||||
_ => return Err(Error::UnexpectedSyntax {
|
_ => return Err(Error::UnexpectedSyntax {
|
||||||
expected:
|
expected:
|
||||||
"identifier, operation, control_flow, assignment, math, function_call or value",
|
"identifier, operation, control_flow, assignment, math, function_call or value",
|
||||||
@ -265,9 +268,7 @@ impl Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Identifier {
|
impl EvaluatorTree for Identifier {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
|
||||||
|
|
||||||
assert_eq!(node.kind(), "identifier");
|
assert_eq!(node.kind(), "identifier");
|
||||||
|
|
||||||
let identifier = &source[node.byte_range()];
|
let identifier = &source[node.byte_range()];
|
||||||
@ -290,35 +291,26 @@ pub struct ControlFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for ControlFlow {
|
impl EvaluatorTree for ControlFlow {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
|
||||||
assert_eq!(node.kind(), "control_flow");
|
assert_eq!(node.kind(), "control_flow");
|
||||||
|
|
||||||
println!("{node:?}");
|
|
||||||
|
|
||||||
// Skip the child nodes for the keywords "if", "then" and "else".
|
|
||||||
|
|
||||||
let if_node = node.child_by_field_name("if_expression").unwrap();
|
let if_node = node.child_by_field_name("if_expression").unwrap();
|
||||||
|
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
||||||
cursor.reset(if_node);
|
|
||||||
|
|
||||||
let if_expression = Expression::new(source, cursor)?;
|
|
||||||
|
|
||||||
println!("{:?}", cursor.node());
|
|
||||||
|
|
||||||
let then_node = node.child_by_field_name("then_statement").unwrap();
|
let then_node = node.child_by_field_name("then_statement").unwrap();
|
||||||
|
let then_statement = Statement::from_syntax_node(then_node, source)?;
|
||||||
|
|
||||||
cursor.reset(then_node);
|
let else_node = node.child_by_field_name("else_statement");
|
||||||
|
let else_statement = if let Some(node) = else_node {
|
||||||
let position = cursor.node();
|
Some(Statement::from_syntax_node(node, source)?)
|
||||||
let then_statement = Statement::new(source, cursor)?;
|
} else {
|
||||||
|
None
|
||||||
cursor.reset(position);
|
};
|
||||||
|
|
||||||
Ok(ControlFlow {
|
Ok(ControlFlow {
|
||||||
if_expression,
|
if_expression,
|
||||||
then_statement,
|
then_statement,
|
||||||
else_statement: None,
|
else_statement,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,18 +334,14 @@ pub struct Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Assignment {
|
impl EvaluatorTree for Assignment {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
|
||||||
cursor.goto_first_child();
|
|
||||||
assert_eq!(node.kind(), "assignment");
|
assert_eq!(node.kind(), "assignment");
|
||||||
|
|
||||||
cursor.goto_next_sibling();
|
let identifier_node = node.child(0).unwrap();
|
||||||
let identifier = Identifier::new(source, cursor)?;
|
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||||
|
|
||||||
cursor.goto_next_sibling();
|
let statement_node = node.child(2).unwrap();
|
||||||
let statement = Statement::new(source, cursor)?;
|
let statement = Statement::from_syntax_node(statement_node, source)?;
|
||||||
|
|
||||||
cursor.goto_next_sibling();
|
|
||||||
|
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
identifier,
|
identifier,
|
||||||
@ -379,15 +367,13 @@ pub struct Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Math {
|
impl EvaluatorTree for Math {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
|
||||||
assert_eq!(node.kind(), "math");
|
assert_eq!(node.kind(), "math");
|
||||||
|
|
||||||
cursor.goto_first_child();
|
let left_node = node.child(0).unwrap();
|
||||||
let left = Expression::new(source, cursor)?;
|
let left = Expression::from_syntax_node(left_node, source)?;
|
||||||
|
|
||||||
cursor.goto_next_sibling();
|
let operator_node = left_node.next_sibling().unwrap();
|
||||||
let operator_node = cursor.node();
|
|
||||||
let operator = match operator_node.kind() {
|
let operator = match operator_node.kind() {
|
||||||
"+" => MathOperator::Add,
|
"+" => MathOperator::Add,
|
||||||
"-" => MathOperator::Subtract,
|
"-" => MathOperator::Subtract,
|
||||||
@ -403,8 +389,8 @@ impl EvaluatorTree for Math {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cursor.goto_next_sibling();
|
let right_node = operator_node.next_sibling().unwrap();
|
||||||
let right = Expression::new(source, cursor)?;
|
let right = Expression::from_syntax_node(right_node, source)?;
|
||||||
|
|
||||||
Ok(Math {
|
Ok(Math {
|
||||||
left,
|
left,
|
||||||
@ -444,22 +430,15 @@ pub struct FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for FunctionCall {
|
impl EvaluatorTree for FunctionCall {
|
||||||
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
|
||||||
assert_eq!(node.kind(), "function_call");
|
assert_eq!(node.kind(), "function_call");
|
||||||
|
|
||||||
cursor.goto_first_child();
|
let identifier_node = node.child(0).unwrap();
|
||||||
let identifier = Identifier::new(source, cursor)?;
|
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
||||||
|
|
||||||
let mut expressions = Vec::new();
|
let mut expressions = Vec::new();
|
||||||
|
|
||||||
for index in 2..node.child_count() - 1 {
|
todo!();
|
||||||
cursor.goto_next_sibling();
|
|
||||||
|
|
||||||
let expression = Expression::new(source, cursor)?;
|
|
||||||
|
|
||||||
expressions.push(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(FunctionCall {
|
Ok(FunctionCall {
|
||||||
identifier,
|
identifier,
|
||||||
|
224
src/value/mod.rs
224
src/value/mod.rs
@ -37,6 +37,50 @@ pub enum Primitive {
|
|||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Primitive {
|
||||||
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
|
match node.kind() {
|
||||||
|
"integer" => Primitive::integer_from_source(source, node.byte_range()),
|
||||||
|
"float" => Primitive::float_from_source(source, node.byte_range()),
|
||||||
|
"boolean" => Primitive::boolean_from_source(source, node.byte_range()),
|
||||||
|
"string" => Primitive::string_from_source(source, node.byte_range()),
|
||||||
|
"empty" => Ok(Primitive::Empty),
|
||||||
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
|
expected: "integer, float, boolean, string or empty",
|
||||||
|
actual: node.kind(),
|
||||||
|
location: node.start_position(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Primitive::Integer(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Primitive::Float(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Primitive::Boolean(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||||
|
|
||||||
|
Ok(Primitive::String(without_quotes.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Eq for Primitive {}
|
impl Eq for Primitive {}
|
||||||
|
|
||||||
impl Ord for Primitive {
|
impl Ord for Primitive {
|
||||||
@ -74,53 +118,90 @@ pub enum Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn from_source(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> {
|
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let node = cursor.node();
|
debug_assert_eq!(node.kind(), "value");
|
||||||
cursor.goto_first_child();
|
|
||||||
let child = cursor.node();
|
|
||||||
|
|
||||||
assert_eq!(node.kind(), "value");
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"integer" | "float" | "boolean" | "string" | "empty" => {
|
"integer" | "float" | "boolean" | "string" | "empty" => Ok(Value::Primitive(
|
||||||
Value::simple_from_syntax_node(node, source)
|
Primitive::from_syntax_node(child, source)?,
|
||||||
}
|
)),
|
||||||
"list" => {
|
"list" => {
|
||||||
let list_length = child.named_child_count();
|
let item_count = child.named_child_count();
|
||||||
let mut values = Vec::with_capacity(list_length);
|
let mut values = Vec::with_capacity(item_count);
|
||||||
|
let mut current_node = child.child(1).unwrap();
|
||||||
|
|
||||||
cursor.goto_first_child();
|
while values.len() < item_count {
|
||||||
|
if current_node.is_named() {
|
||||||
|
let value = Value::from_syntax_node(current_node, source)?;
|
||||||
|
|
||||||
for value_node in child.children_by_field_name("item", &mut cursor) {
|
values.push(value);
|
||||||
let value = Value::simple_from_syntax_node(value_node, source)?;
|
}
|
||||||
|
|
||||||
values.push(value);
|
current_node = current_node.next_sibling().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::List(values))
|
Ok(Value::List(values))
|
||||||
}
|
}
|
||||||
"table" => {
|
"table" => {
|
||||||
let mut column_names = Vec::new();
|
let mut current_node = child.child(0).unwrap();
|
||||||
|
let header_and_row_count = child.named_child_count();
|
||||||
|
|
||||||
let mut table = Table::new(column_names);
|
let mut headers = Vec::new();
|
||||||
|
let mut rows = Vec::new();
|
||||||
|
|
||||||
|
while headers.len() + rows.len() < header_and_row_count {
|
||||||
|
println!("{current_node:?}");
|
||||||
|
|
||||||
|
if current_node.kind() == "identifier" {
|
||||||
|
let identifier = Identifier::from_syntax_node(current_node, source)?;
|
||||||
|
let identifier_text = identifier.take_inner();
|
||||||
|
|
||||||
|
headers.push(identifier_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if current_node.kind() == "list" {
|
||||||
|
let value = Value::list_from_syntax_node(current_node, source)?;
|
||||||
|
let row = value.into_inner_list()?;
|
||||||
|
|
||||||
|
rows.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(node) = current_node.next_sibling() {
|
||||||
|
current_node = node;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let table = Table::from_raw_parts(headers, rows);
|
||||||
|
|
||||||
Ok(Value::Table(table))
|
Ok(Value::Table(table))
|
||||||
}
|
}
|
||||||
"map" => {
|
"map" => {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
let pair_count = child.named_child_count();
|
||||||
let mut current_key = String::new();
|
let mut current_key = String::new();
|
||||||
|
let mut current_node = child.child(0).unwrap();
|
||||||
|
|
||||||
for key_value_node in child.children_by_field_name("key_value_pair", &mut cursor) {
|
while map.len() < pair_count {
|
||||||
if key_value_node.kind() == "identifier" {
|
if current_node.kind() == "identifier" {
|
||||||
let identifier_text = &source[key_value_node.byte_range()];
|
let identifier_text = &source[current_node.byte_range()];
|
||||||
current_key = identifier_text.to_string();
|
current_key = identifier_text.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
if key_value_node.kind() == "value" {
|
if current_node.kind() == "value" {
|
||||||
let value = Value::simple_from_syntax_node(key_value_node, source)?;
|
let value = Value::from_syntax_node(current_node, source)?;
|
||||||
|
|
||||||
map.set_value(current_key.to_string(), value)?;
|
map.set_value(current_key.to_string(), value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(node) = current_node.next_sibling() {
|
||||||
|
current_node = node;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Map(map))
|
||||||
@ -133,17 +214,17 @@ impl Value {
|
|||||||
for index in 0..child_count {
|
for index in 0..child_count {
|
||||||
let child = child.child(index).unwrap();
|
let child = child.child(index).unwrap();
|
||||||
|
|
||||||
if child.kind() == "identifier" {
|
// if child.kind() == "identifier" {
|
||||||
let identifier = Identifier::new(source, cursor)?;
|
// let identifier = Identifier::new(source, cursor)?;
|
||||||
|
|
||||||
identifiers.push(identifier)
|
// identifiers.push(identifier)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if child.kind() == "statement" {
|
// if child.kind() == "statement" {
|
||||||
let statement = Statement::new(source, cursor)?;
|
// let statement = Statement::new(source, cursor)?;
|
||||||
|
|
||||||
statements.push(statement)
|
// statements.push(statement)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Function(Function::new(identifiers, statements)))
|
Ok(Value::Function(Function::new(identifiers, statements)))
|
||||||
@ -156,56 +237,53 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a simple value from the given source code and a node in the
|
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
/// syntax tree.
|
debug_assert_eq!(node.kind(), "list");
|
||||||
///
|
|
||||||
///
|
|
||||||
pub fn simple_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
|
||||||
let child = node.child(0).unwrap();
|
|
||||||
|
|
||||||
match child.kind() {
|
let item_count = node.named_child_count();
|
||||||
"integer" => Value::integer_from_source(source, child.byte_range()),
|
let mut values = Vec::with_capacity(item_count);
|
||||||
"float" => Value::float_from_source(source, child.byte_range()),
|
let mut current_node = node.child(1).unwrap();
|
||||||
"boolean" => Value::boolean_from_source(source, child.byte_range()),
|
|
||||||
"string" => Value::string_from_source(source, child.byte_range()),
|
while values.len() < item_count {
|
||||||
"empty" => Ok(Value::Primitive(Primitive::Empty)),
|
if current_node.is_named() {
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
let value = Value::from_syntax_node(current_node, source)?;
|
||||||
expected: "integer, float, boolean, string or empty",
|
|
||||||
actual: child.kind(),
|
values.push(value);
|
||||||
location: child.start_position(),
|
}
|
||||||
}),
|
|
||||||
|
current_node = current_node.next_sibling().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(Value::List(values))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
// pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
// let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
// let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Primitive(Primitive::Integer(raw)))
|
// Ok(Primitive::Integer(raw))
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
// pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
// let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
// let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Primitive(Primitive::Float(raw)))
|
// Ok(Primitive::Float(raw))
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
// pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
// let value_snippet = &source[byte_range];
|
||||||
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
// let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||||
|
|
||||||
Ok(Value::Primitive(Primitive::Boolean(raw)))
|
// Ok(Primitive::Boolean(raw))
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
// pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
let value_snippet = &source[byte_range];
|
// let value_snippet = &source[byte_range];
|
||||||
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
// let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||||
|
|
||||||
Ok(Value::Primitive(Primitive::String(
|
// Ok(Primitive::String(without_quotes.to_string()))
|
||||||
without_quotes.to_string(),
|
// }
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
ValueType::from(self)
|
ValueType::from(self)
|
||||||
@ -532,7 +610,13 @@ impl Display for Value {
|
|||||||
Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int),
|
Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int),
|
||||||
Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean),
|
Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean),
|
||||||
Value::Primitive(Primitive::Empty) => write!(f, "()"),
|
Value::Primitive(Primitive::Empty) => write!(f, "()"),
|
||||||
Value::List(list) => Table::from(list).fmt(f),
|
Value::List(list) => {
|
||||||
|
write!(f, "(")?;
|
||||||
|
for value in list {
|
||||||
|
write!(f, " {value} ")?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
Value::Map(map) => write!(f, "{map}"),
|
Value::Map(map) => write!(f, "{map}"),
|
||||||
Value::Table(table) => write!(f, "{table}"),
|
Value::Table(table) => write!(f, "{table}"),
|
||||||
Value::Function(function) => write!(f, "{function}"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
|
@ -8,26 +8,42 @@ use std::{
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
header: Vec<String>,
|
headers: Vec<String>,
|
||||||
rows: Vec<Vec<Value>>,
|
rows: Vec<Vec<Value>>,
|
||||||
primary_key_index: usize,
|
primary_key_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn new(column_names: Vec<String>) -> Self {
|
pub fn new(headers: Vec<String>) -> Self {
|
||||||
Table {
|
Table {
|
||||||
header: column_names,
|
headers,
|
||||||
rows: Vec::new(),
|
rows: Vec::new(),
|
||||||
primary_key_index: 0,
|
primary_key_index: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_capacity(capacity: usize, headers: Vec<String>) -> Self {
|
||||||
|
Table {
|
||||||
|
headers,
|
||||||
|
rows: Vec::with_capacity(capacity),
|
||||||
|
primary_key_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_raw_parts(headers: Vec<String>, rows: Vec<Vec<Value>>) -> Self {
|
||||||
|
Table {
|
||||||
|
headers,
|
||||||
|
rows,
|
||||||
|
primary_key_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reserve(&mut self, additional: usize) {
|
pub fn reserve(&mut self, additional: usize) {
|
||||||
self.rows.reserve(additional);
|
self.rows.reserve(additional);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn column_names(&self) -> &Vec<String> {
|
pub fn column_names(&self) -> &Vec<String> {
|
||||||
&self.header
|
&self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rows(&self) -> &Vec<Vec<Value>> {
|
pub fn rows(&self) -> &Vec<Vec<Value>> {
|
||||||
@ -47,9 +63,9 @@ impl Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, row: Vec<Value>) -> Result<()> {
|
pub fn insert(&mut self, row: Vec<Value>) -> Result<()> {
|
||||||
if row.len() != self.header.len() {
|
if row.len() != self.headers.len() {
|
||||||
return Err(Error::WrongColumnAmount {
|
return Err(Error::WrongColumnAmount {
|
||||||
expected: self.header.len(),
|
expected: self.headers.len(),
|
||||||
actual: row.len(),
|
actual: row.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -82,10 +98,10 @@ impl Table {
|
|||||||
let mut new_row = Vec::new();
|
let mut new_row = Vec::new();
|
||||||
|
|
||||||
for (i, value) in row.iter().enumerate() {
|
for (i, value) in row.iter().enumerate() {
|
||||||
let column_name = self.header.get(i).unwrap();
|
let column_name = self.headers.get(i).unwrap();
|
||||||
let new_table_column_index =
|
let new_table_column_index =
|
||||||
new_table
|
new_table
|
||||||
.header
|
.headers
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(index, new_column_name)| {
|
.find_map(|(index, new_column_name)| {
|
||||||
@ -125,7 +141,7 @@ impl Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> {
|
pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> {
|
||||||
let mut filtered = Table::new(self.header.clone());
|
let mut filtered = Table::new(self.headers.clone());
|
||||||
let column_index = self.get_column_index(column_name)?;
|
let column_index = self.get_column_index(column_name)?;
|
||||||
|
|
||||||
for row in &self.rows {
|
for row in &self.rows {
|
||||||
@ -140,7 +156,7 @@ impl Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
|
pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
|
||||||
let column_names = &self.header;
|
let column_names = &self.headers;
|
||||||
for (i, column) in column_names.iter().enumerate() {
|
for (i, column) in column_names.iter().enumerate() {
|
||||||
if column == column_name {
|
if column == column_name {
|
||||||
return Some(i);
|
return Some(i);
|
||||||
@ -157,7 +173,7 @@ impl Display for Table {
|
|||||||
table
|
table
|
||||||
.load_preset("││──├─┼┤│ ┬┴╭╮╰╯")
|
.load_preset("││──├─┼┤│ ┬┴╭╮╰╯")
|
||||||
.set_content_arrangement(ContentArrangement::Dynamic)
|
.set_content_arrangement(ContentArrangement::Dynamic)
|
||||||
.set_header(&self.header);
|
.set_header(&self.headers);
|
||||||
|
|
||||||
for row in &self.rows {
|
for row in &self.rows {
|
||||||
let row = row.iter().map(|value| {
|
let row = row.iter().map(|value| {
|
||||||
@ -209,7 +225,7 @@ impl Display for Table {
|
|||||||
table.add_row(row);
|
table.add_row(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.header.is_empty() {
|
if self.headers.is_empty() {
|
||||||
table.set_header(["empty"]);
|
table.set_header(["empty"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +376,7 @@ impl Eq for Table {}
|
|||||||
|
|
||||||
impl PartialEq for Table {
|
impl PartialEq for Table {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
if self.header != other.header {
|
if self.headers != other.headers {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,12 +386,12 @@ impl PartialEq for Table {
|
|||||||
|
|
||||||
impl PartialOrd for Table {
|
impl PartialOrd for Table {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
self.header.partial_cmp(&other.header)
|
self.headers.partial_cmp(&other.headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Table {
|
impl Ord for Table {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
self.header.cmp(&other.header)
|
self.headers.cmp(&other.headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user