mirror of https://github.com/kdl-org/kdl.git
node, identifier, and comments done
This commit is contained in:
parent
950d5bfc85
commit
100a736145
13
src/node.rs
13
src/node.rs
|
|
@ -1 +1,12 @@
|
||||||
pub struct Node;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Node {
|
||||||
|
pub name: String,
|
||||||
|
pub values: Vec<NodeValue>,
|
||||||
|
pub properties: HashMap<String, NodeValue>,
|
||||||
|
pub children: Vec<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum NodeValue {}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::combinator::{map, opt};
|
use nom::character::complete::{alpha1, alphanumeric1, one_of};
|
||||||
|
use nom::combinator::{map, not, opt, recognize};
|
||||||
use nom::multi::{many0, many1};
|
use nom::multi::{many0, many1};
|
||||||
use nom::sequence::{delimited, preceded};
|
use nom::sequence::{delimited, pair, preceded};
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
||||||
use crate::error::{ErrorKind, NodeParseError};
|
use crate::error::{ErrorKind, NodeParseError};
|
||||||
use crate::node::Node;
|
use crate::node::{Node, NodeValue};
|
||||||
|
|
||||||
/// `document := linespace* (node (newline document)?)?`
|
/// `document := linespace* (node (newline document)?)?`
|
||||||
pub(crate) fn nodes(input: &str) -> IResult<&str, Vec<Node>, NodeParseError<&str>> {
|
pub(crate) fn nodes(input: &str) -> IResult<&str, Vec<Node>, NodeParseError<&str>> {
|
||||||
|
|
@ -14,16 +17,70 @@ pub(crate) fn nodes(input: &str) -> IResult<&str, Vec<Node>, NodeParseError<&str
|
||||||
many0(node)(input)
|
many0(node)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum NodeArg<'a> {
|
||||||
|
Value(NodeValue),
|
||||||
|
Property(&'a str, NodeValue),
|
||||||
|
}
|
||||||
|
|
||||||
/// `node := identifier (node-space node-argument)* (node-space node-document)?`
|
/// `node := identifier (node-space node-argument)* (node-space node-document)?`
|
||||||
pub(crate) fn node(input: &str) -> IResult<&str, Node, NodeParseError<&str>> {
|
pub(crate) fn node(input: &str) -> IResult<&str, Node, NodeParseError<&str>> {
|
||||||
let (input, tag) = identifier(input)?;
|
let (input, tag) = identifier(input)?;
|
||||||
let (input, args) = many0(preceded(node_space, node_arg))(input)?;
|
let (input, args) = many0(preceded(node_space, node_arg))(input)?;
|
||||||
let (input, children) = opt(preceded(node_space, node_children))(input)?;
|
let (input, children) = opt(preceded(node_space, node_children))(input)?;
|
||||||
todo!();
|
let (values, properties): (Vec<NodeArg>, Vec<NodeArg>) = args
|
||||||
|
.into_iter()
|
||||||
|
.partition(|arg| matches!(arg, NodeArg::Value(_)));
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
Node {
|
||||||
|
name: tag.into(),
|
||||||
|
children: children.unwrap_or_else(Vec::new),
|
||||||
|
values: values
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| match arg {
|
||||||
|
NodeArg::Value(val) => val,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
properties: properties.into_iter().fold(HashMap::new(), |mut acc, arg| {
|
||||||
|
match arg {
|
||||||
|
NodeArg::Property(key, value) => {
|
||||||
|
acc.insert(String::from(key), value);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
acc
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `identifier := [a-zA-Z] [a-zA-Z0-9!#$%&'*+\-./:<>?@\^_|~]* | string`
|
/// `identifier := [a-zA-Z_] [a-zA-Z0-9!#$%&'*+\-./:<>?@\^_|~]* | string`
|
||||||
fn identifier(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
fn identifier(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
||||||
|
alt((
|
||||||
|
recognize(pair(
|
||||||
|
alt((alpha1, tag("_"))),
|
||||||
|
many0(alt((
|
||||||
|
alphanumeric1,
|
||||||
|
recognize(one_of("~!@#$%^&*-_+./:<>?")),
|
||||||
|
))),
|
||||||
|
)),
|
||||||
|
string,
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_arg(input: &str) -> IResult<&str, NodeArg, NodeParseError<&str>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node_children(input: &str) -> IResult<&str, Vec<Node>, NodeParseError<&str>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This should be much more specific about what escapes are allowed.
|
||||||
|
/// `string := '"' ('\\' ["\\] | [^"])* '"'`
|
||||||
|
fn string(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,12 +94,18 @@ fn node_space(input: &str) -> IResult<&str, (), NodeParseError<&str>> {
|
||||||
|
|
||||||
/// `single-line-comment := '//' ('\r' [^\n] | [^\r\n])* newline`
|
/// `single-line-comment := '//' ('\r' [^\n] | [^\r\n])* newline`
|
||||||
fn single_line_comment(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
fn single_line_comment(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
||||||
todo!()
|
let (input, _) = tag("//")(input)?;
|
||||||
|
let (input, comment) = recognize(many0(alt((
|
||||||
|
preceded(tag("\r"), not(tag("\n"))),
|
||||||
|
not(tag("\r\n")),
|
||||||
|
))))(input)?;
|
||||||
|
let (input, _) = newline(input)?;
|
||||||
|
Ok((input, comment))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `multi-line-comment := '/*' ('*' [^\/] | [^*])* '*/'`
|
/// `multi-line-comment := '/*' ('*' [^\/] | [^*])* '*/'`
|
||||||
fn multi_line_comment(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
fn multi_line_comment(input: &str) -> IResult<&str, &str, NodeParseError<&str>> {
|
||||||
todo!()
|
delimited(tag("/*"), recognize(many0(not(tag("*/")))), tag("*/"))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `escline := '\\' ws* (single-line-comment | newline)`
|
/// `escline := '\\' ws* (single-line-comment | newline)`
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue