feat(types): add type annotation support (#31)

This commit is contained in:
Kat Marchán 2022-04-22 12:00:32 -07:00 committed by GitHub
parent e242613127
commit 16c82f1ec1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 4 deletions

View File

@ -254,7 +254,7 @@ foo 1 2 \"three\" null true bar=\"baz\" {
- 1 - 1
- 2 - 2
- \"three\" - \"three\"
something \"else\"\r (mytype)something (\"name\")\"else\"\r
} }
null_id null_prop=null null_id null_prop=null

View File

@ -11,7 +11,7 @@ use crate::{KdlError, KdlErrorKind, KdlIdentifier, KdlValue};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct KdlEntry { pub struct KdlEntry {
pub(crate) leading: Option<String>, pub(crate) leading: Option<String>,
pub(crate) ty: Option<String>, pub(crate) ty: Option<KdlIdentifier>,
pub(crate) value: KdlValue, pub(crate) value: KdlValue,
pub(crate) value_repr: Option<String>, pub(crate) value_repr: Option<String>,
pub(crate) name: Option<KdlIdentifier>, pub(crate) name: Option<KdlIdentifier>,
@ -109,7 +109,7 @@ impl Display for KdlEntry {
write!(f, "{}", leading)?; write!(f, "{}", leading)?;
} }
if let Some(ty) = &self.ty { if let Some(ty) = &self.ty {
write!(f, "{}", ty)?; write!(f, "({})", ty)?;
} }
if let Some(name) = &self.name { if let Some(name) = &self.name {
write!(f, "{}=", name)?; write!(f, "{}=", name)?;

View File

@ -14,7 +14,7 @@ use crate::{KdlDocument, KdlEntry, KdlError, KdlErrorKind, KdlIdentifier, KdlVal
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct KdlNode { pub struct KdlNode {
pub(crate) leading: Option<String>, pub(crate) leading: Option<String>,
pub(crate) ty: Option<String>, pub(crate) ty: Option<KdlIdentifier>,
pub(crate) name: KdlIdentifier, pub(crate) name: KdlIdentifier,
// TODO: consider using `hashlink` for this instead, later. // TODO: consider using `hashlink` for this instead, later.
pub(crate) entries: Vec<KdlEntry>, pub(crate) entries: Vec<KdlEntry>,
@ -52,6 +52,20 @@ impl KdlNode {
self.name = name.into(); self.name = name.into();
} }
/// Gets the node's type, if any.
pub fn ty(&self) -> Option<&KdlIdentifier> {
self.ty.as_ref()
}
/// Gets a mutable reference to the node's type.
pub fn ty_mut(&mut self) -> &mut Option<KdlIdentifier> {
&mut self.ty
}
pub fn set_ty(&mut self, ty: impl Into<KdlIdentifier>) {
self.ty = Some(ty.into());
}
/// Returns a reference to this node's entries (arguments and properties). /// Returns a reference to this node's entries (arguments and properties).
pub fn entries(&self) -> &[KdlEntry] { pub fn entries(&self) -> &[KdlEntry] {
&self.entries &self.entries

View File

@ -23,6 +23,7 @@ pub(crate) fn document(input: &str) -> IResult<&str, KdlDocument, KdlParseError<
pub(crate) fn node(input: &str) -> IResult<&str, KdlNode, KdlParseError<&str>> { pub(crate) fn node(input: &str) -> IResult<&str, KdlNode, KdlParseError<&str>> {
let (input, leading) = all_whitespace(input)?; let (input, leading) = all_whitespace(input)?;
let (input, ty) = opt(annotation)(input)?;
let (input, name) = identifier(input)?; let (input, name) = identifier(input)?;
let (input, entries) = many0(entry)(input)?; let (input, entries) = many0(entry)(input)?;
let (input, children) = opt(children)(input)?; let (input, children) = opt(children)(input)?;
@ -33,6 +34,7 @@ pub(crate) fn node(input: &str) -> IResult<&str, KdlNode, KdlParseError<&str>> {
let mut node = KdlNode::new(name); let mut node = KdlNode::new(name);
node.set_leading(leading); node.set_leading(leading);
node.set_trailing(trailing); node.set_trailing(trailing);
node.ty = ty;
let ents = node.entries_mut(); let ents = node.entries_mut();
*ents = entries; *ents = entries;
if let Some((before, children)) = children { if let Some((before, children)) = children {
@ -70,10 +72,12 @@ pub(crate) fn entry(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>>
fn property(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { fn property(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> {
let (input, leading) = recognize(many0(node_space))(input)?; let (input, leading) = recognize(many0(node_space))(input)?;
let (input, ty) = opt(annotation)(input)?;
let (input, name) = identifier(input)?; let (input, name) = identifier(input)?;
let (input, _) = tag("=")(input)?; let (input, _) = tag("=")(input)?;
let (input, (raw, value)) = value(input)?; let (input, (raw, value)) = value(input)?;
let mut entry = KdlEntry::new_prop(name, value); let mut entry = KdlEntry::new_prop(name, value);
entry.ty = ty;
entry.set_leading(if leading.is_empty() { " " } else { leading }); entry.set_leading(if leading.is_empty() { " " } else { leading });
entry.set_value_repr(raw); entry.set_value_repr(raw);
Ok((input, entry)) Ok((input, entry))
@ -81,8 +85,10 @@ fn property(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> {
fn argument(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { fn argument(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> {
let (input, leading) = recognize(many0(node_space))(input)?; let (input, leading) = recognize(many0(node_space))(input)?;
let (input, ty) = opt(annotation)(input)?;
let (input, (raw, value)) = value(input)?; let (input, (raw, value)) = value(input)?;
let mut entry = KdlEntry::new(value); let mut entry = KdlEntry::new(value);
entry.ty = ty;
entry.set_leading(if leading.is_empty() { " " } else { leading }); entry.set_leading(if leading.is_empty() { " " } else { leading });
entry.set_value_repr(raw); entry.set_value_repr(raw);
Ok((input, entry)) Ok((input, entry))
@ -110,6 +116,13 @@ fn children(input: &str) -> IResult<&str, (&str, KdlDocument), KdlParseError<&st
Ok((input, (before, children))) Ok((input, (before, children)))
} }
fn annotation(input: &str) -> IResult<&str, KdlIdentifier, KdlParseError<&str>> {
let (input, _) = tag("(")(input)?;
let (input, ty) = identifier(input)?;
let (input, _) = tag(")")(input)?;
Ok((input, ty))
}
fn all_whitespace(input: &str) -> IResult<&str, &str, KdlParseError<&str>> { fn all_whitespace(input: &str) -> IResult<&str, &str, KdlParseError<&str>> {
recognize(many0(alt((comment, unicode_space, newline))))(input) recognize(many0(alt((comment, unicode_space, newline))))(input)
} }