use crate::parse::identifiers::parse_identifier_reference;
use crate::parse::parse_comment;
use rust_decimal::Decimal;
use sdml_core::load::ModuleLoader as ModuleLoaderTrait;
use sdml_core::model::members::{Ordering, Uniqueness};
use sdml_core::model::values::{
Binary, LanguageString, LanguageTag, MappingValue, SequenceOfValues, SimpleValue, Value,
ValueConstructor,
};
use sdml_core::model::HasSourceSpan;
use sdml_core::syntax::{
FIELD_NAME_BYTE, FIELD_NAME_DOMAIN, FIELD_NAME_ELEMENT, FIELD_NAME_NAME, FIELD_NAME_ORDERING,
FIELD_NAME_RANGE, FIELD_NAME_UNIQUENESS, FIELD_NAME_VALUE, NODE_KIND_BINARY, NODE_KIND_BOOLEAN,
NODE_KIND_DECIMAL, NODE_KIND_DOUBLE, NODE_KIND_IDENTIFIER_REFERENCE, NODE_KIND_INTEGER,
NODE_KIND_IRI, NODE_KIND_LANGUAGE_TAG, NODE_KIND_LINE_COMMENT, NODE_KIND_MAPPING_VALUE,
NODE_KIND_QUOTED_STRING, NODE_KIND_SEQUENCE_OF_VALUES, NODE_KIND_SEQUENCE_ORDERING,
NODE_KIND_SEQUENCE_UNIQUENESS, NODE_KIND_SIMPLE_VALUE, NODE_KIND_STRING, NODE_KIND_UNSIGNED,
NODE_KIND_VALUE, NODE_KIND_VALUE_CONSTRUCTOR,
};
use sdml_errors::Error;
use std::str::FromStr;
use tree_sitter::TreeCursor;
use url::Url;
use super::ParseContext;
pub(crate) fn parse_value<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<Value, Error> {
let node = cursor.node();
rule_fn!("value", node);
for node in cursor.node().named_children(cursor) {
check_node!(context, RULE_NAME, &node);
match node.kind() {
NODE_KIND_SIMPLE_VALUE => {
return Ok(parse_simple_value(context, &mut node.walk())?.into());
}
NODE_KIND_VALUE_CONSTRUCTOR => {
return Ok(parse_value_constructor(context, &mut node.walk())?.into());
}
NODE_KIND_IDENTIFIER_REFERENCE => {
return Ok(parse_identifier_reference(context, &mut node.walk())?.into());
}
NODE_KIND_MAPPING_VALUE => {
return Ok(parse_mapping_value(context, &mut node.walk())?.into());
}
NODE_KIND_SEQUENCE_OF_VALUES => {
return Ok(parse_sequence_of_values(context, &mut node.walk())?.into());
}
NODE_KIND_LINE_COMMENT => {}
_ => {
unexpected_node!(
context,
RULE_NAME,
node,
[
NODE_KIND_SIMPLE_VALUE,
NODE_KIND_VALUE_CONSTRUCTOR,
NODE_KIND_IDENTIFIER_REFERENCE,
NODE_KIND_SEQUENCE_OF_VALUES,
]
);
}
}
}
rule_unreachable!(RULE_NAME, cursor);
}
pub(crate) fn parse_simple_value<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<SimpleValue, Error> {
let node = cursor.node();
rule_fn!("simple_value", node);
for node in cursor.node().named_children(cursor) {
check_node!(context, RULE_NAME, &node);
match node.kind() {
NODE_KIND_BOOLEAN => {
let value = context.node_source(&node)?;
return if value == "⊤" {
Ok(SimpleValue::Boolean(true))
} else if value == "⊥" {
Ok(SimpleValue::Boolean(false))
} else {
match bool::from_str(value) {
Ok(value) => Ok(SimpleValue::Boolean(value)),
Err(err) => {
invalid_value_for_node_type!(
context,
RULE_NAME,
node,
value,
Some(err)
);
}
}
};
}
NODE_KIND_UNSIGNED => {
let value = context.node_source(&node)?;
return match u64::from_str(value) {
Ok(value) => Ok(SimpleValue::Unsigned(value)),
Err(err) => {
invalid_value_for_node_type!(context, RULE_NAME, node, value, Some(err));
}
};
}
NODE_KIND_INTEGER => {
let value = context.node_source(&node)?;
return match i64::from_str(value) {
Ok(value) => Ok(SimpleValue::Integer(value)),
Err(err) => {
invalid_value_for_node_type!(context, RULE_NAME, node, value, Some(err));
}
};
}
NODE_KIND_DECIMAL => {
let value = context.node_source(&node)?;
return match Decimal::from_str(value) {
Ok(value) => Ok(SimpleValue::Decimal(value)),
Err(err) => {
invalid_value_for_node_type!(context, RULE_NAME, node, value, Some(err));
}
};
}
NODE_KIND_DOUBLE => {
let value = context.node_source(&node)?;
return match f64::from_str(value) {
Ok(value) => Ok(SimpleValue::Double(value.into())),
Err(err) => {
invalid_value_for_node_type!(context, RULE_NAME, node, value, Some(err));
}
};
}
NODE_KIND_STRING => {
let value = parse_string(context, &mut node.walk())?;
return Ok(SimpleValue::String(value));
}
NODE_KIND_IRI => {
let value = context.node_source(&node)?;
return match Url::from_str(&value[1..(value.len() - 1)]) {
Ok(value) => Ok(SimpleValue::IriReference(value)),
Err(err) => {
invalid_value_for_node_type!(context, RULE_NAME, node, value, Some(err));
}
};
}
NODE_KIND_BINARY => {
let value = parse_binary(context, &mut node.walk())?;
return Ok(SimpleValue::Binary(value));
}
NODE_KIND_LINE_COMMENT => {}
_ => {
unexpected_node!(
context,
RULE_NAME,
node,
[
NODE_KIND_STRING,
NODE_KIND_DOUBLE,
NODE_KIND_DECIMAL,
NODE_KIND_INTEGER,
NODE_KIND_BOOLEAN,
NODE_KIND_IRI,
]
);
}
}
}
rule_unreachable!(RULE_NAME, cursor);
}
fn parse_string<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<LanguageString, Error> {
rule_fn!("string", cursor.node());
let root_node = cursor.node();
let mut has_next = cursor.goto_first_child();
if has_next {
let mut value = String::new();
let mut language = None;
while has_next {
let node = cursor.node();
context.check_if_error(&node, RULE_NAME)?;
if node.is_named() {
match node.kind() {
NODE_KIND_QUOTED_STRING => {
let node_value = context.node_source(&node)?;
value = node_value[1..(node_value.len() - 1)].to_string();
}
NODE_KIND_LANGUAGE_TAG => {
let node_value = context.node_source(&node)?;
language = Some(
LanguageTag::new_unchecked(&node_value[1..])
.with_source_span(node.into()),
);
}
NODE_KIND_LINE_COMMENT => {
let comment = parse_comment(context, &node)?;
context.push_comment(comment);
}
_ => {
unexpected_node!(
context,
RULE_NAME,
node,
[NODE_KIND_QUOTED_STRING, NODE_KIND_LANGUAGE_TAG,]
);
}
}
}
has_next = cursor.goto_next_sibling();
}
assert!(cursor.goto_parent());
return Ok(LanguageString::new(&value, language).with_source_span(root_node.into()));
}
unreachable!()
}
fn parse_binary<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<Binary, Error> {
rule_fn!("binary", cursor.node());
let mut result: Vec<u8> = Default::default();
for node in cursor
.node()
.children_by_field_name(FIELD_NAME_BYTE, cursor)
{
context.check_if_error(&node, RULE_NAME)?;
let value = context.node_source(&node)?;
let value = u8::from_str_radix(value, 16).expect("Invalid value for Byte");
result.push(value);
}
Ok(result.into())
}
fn parse_value_constructor<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<ValueConstructor, Error> {
let node = cursor.node();
rule_fn!("value_constructor", node);
let child = node.child_by_field_name(FIELD_NAME_NAME).unwrap();
context.check_if_error(&child, RULE_NAME)?;
let name = parse_identifier_reference(context, &mut child.walk())?;
let child = node.child_by_field_name(FIELD_NAME_VALUE).unwrap();
context.check_if_error(&child, RULE_NAME)?;
let value = parse_simple_value(context, &mut child.walk())?;
Ok(ValueConstructor::new(name, value).with_source_span(node.into()))
}
fn parse_mapping_value<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<MappingValue, Error> {
let node = cursor.node();
rule_fn!("mapping_value", node);
let child = node_field_named!(
context,
RULE_NAME,
node,
FIELD_NAME_DOMAIN,
NODE_KIND_SIMPLE_VALUE
);
let domain = parse_simple_value(context, &mut child.walk())?;
let child = node_field_named!(context, RULE_NAME, node, FIELD_NAME_RANGE, NODE_KIND_VALUE);
context.check_if_error(&child, RULE_NAME)?;
let range = parse_value(context, &mut child.walk())?;
Ok(MappingValue::new(domain, range).with_source_span(node.into()))
}
fn parse_sequence_of_values<'a>(
context: &mut ParseContext<'a>,
cursor: &mut TreeCursor<'a>,
) -> Result<SequenceOfValues, Error> {
let node = cursor.node();
rule_fn!("sequence_of_values", node);
let mut sequence = SequenceOfValues::default().with_source_span(node.into());
if let Some(ordering) = optional_node_field_named!(
context,
RULE_NAME,
node,
FIELD_NAME_ORDERING,
NODE_KIND_SEQUENCE_ORDERING
) {
sequence.set_ordering(Ordering::from_str(context.node_source(&ordering)?)?);
}
if let Some(uniqueness) = optional_node_field_named!(
context,
RULE_NAME,
node,
FIELD_NAME_UNIQUENESS,
NODE_KIND_SEQUENCE_UNIQUENESS
) {
sequence.set_uniqueness(Uniqueness::from_str(context.node_source(&uniqueness)?)?);
}
for node in node.children_by_field_name(FIELD_NAME_ELEMENT, cursor) {
check_node!(context, RULE_NAME, &node);
match node.kind() {
NODE_KIND_SIMPLE_VALUE => {
sequence.push(parse_simple_value(context, &mut node.walk())?);
}
NODE_KIND_VALUE_CONSTRUCTOR => {
sequence.push(parse_value_constructor(context, &mut node.walk())?);
}
NODE_KIND_IDENTIFIER_REFERENCE => {
sequence.push(parse_identifier_reference(context, &mut node.walk())?);
}
NODE_KIND_LINE_COMMENT => {
let comment = parse_comment(context, &node)?;
context.push_comment(comment);
}
_ => {
unexpected_node!(
context,
RULE_NAME,
node,
[
NODE_KIND_SIMPLE_VALUE,
NODE_KIND_VALUE_CONSTRUCTOR,
NODE_KIND_IDENTIFIER_REFERENCE,
]
);
}
}
}
Ok(sequence)
}