feat(parser): Associate a vector of nasps with every struct, enum, nasp
This feature makes it possible to generate these types actually in namespaces and not only in one toplevel.
This commit is contained in:
parent
4a32f0d2f4
commit
3c3ee23c2b
|
@ -27,15 +27,23 @@ use crate::lexing::TokenKind;
|
|||
|
||||
use super::unchecked::{self, DeriveValue};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub enum Variant {
|
||||
Structure,
|
||||
Enumeration,
|
||||
Structure {
|
||||
namespace: Vec<Identifier>,
|
||||
},
|
||||
Enumeration {
|
||||
namespace: Vec<Identifier>,
|
||||
},
|
||||
Namespace,
|
||||
/// The first (implicit) namespace, containing everything
|
||||
RootNamespace,
|
||||
Function,
|
||||
NamedType,
|
||||
Primitive,
|
||||
NamedType,
|
||||
DocNamedType,
|
||||
|
||||
/// Implicit default, this is not something that _should_ ever be exposed to the public API
|
||||
Void,
|
||||
}
|
||||
|
||||
|
@ -278,7 +286,7 @@ impl From<&DocIdentifier> for Identifier {
|
|||
fn from(value: &DocIdentifier) -> Self {
|
||||
Self {
|
||||
name: value.name.to_owned(),
|
||||
variant: value.variant,
|
||||
variant: value.variant.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ pub struct CommandSpec {
|
|||
impl From<CommandSpec> for Namespace {
|
||||
fn from(value: CommandSpec) -> Self {
|
||||
Self {
|
||||
name: Token::get_dummy(),
|
||||
name: Token::default(),
|
||||
functions: value.functions,
|
||||
structures: value.structures,
|
||||
enumerations: value.enumerations,
|
||||
|
@ -144,6 +144,7 @@ pub struct Structure {
|
|||
pub identifier: Token, // Will later become an Identifier
|
||||
pub contents: Vec<DocNamedType>,
|
||||
pub attributes: Vec<Attribute>,
|
||||
pub namespaces: Vec<Token>, // Will later become an Identifier
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
|
@ -151,6 +152,7 @@ pub struct Enumeration {
|
|||
pub identifier: Token, // Will later become an Identifier
|
||||
pub states: Vec<DocToken>, // Will later become an Identifier
|
||||
pub attributes: Vec<Attribute>,
|
||||
pub namespaces: Vec<Token>, // Will later become an Identifier
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
|
|
|
@ -149,14 +149,6 @@ impl Token {
|
|||
pub fn span(&self) -> &TokenSpan {
|
||||
&self.span
|
||||
}
|
||||
|
||||
/// Get a dummy token, this is intended for error handling
|
||||
pub fn get_dummy() -> Token {
|
||||
Self {
|
||||
span: TokenSpan { start: 0, end: 0 },
|
||||
kind: TokenKind::Dummy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Possibly kinds of tokens
|
||||
|
@ -184,9 +176,10 @@ pub enum TokenKind {
|
|||
|
||||
Comment(String),
|
||||
|
||||
/// This is not a real TokenKind, but only used for error handling
|
||||
#[default]
|
||||
Dummy,
|
||||
/// This tokenkind is here support usages of [`mem::take`], this should never be exposed in the
|
||||
/// final parsed output.
|
||||
DefaultTokenKind,
|
||||
}
|
||||
|
||||
impl TokenKind {
|
||||
|
@ -233,7 +226,6 @@ impl Display for TokenKind {
|
|||
TokenKind::Semicolon => f.write_str("SEMICOLON"),
|
||||
TokenKind::Comma => f.write_str("COMMA"),
|
||||
TokenKind::Arrow => f.write_str("ARROW"),
|
||||
TokenKind::Dummy => f.write_str("DUMMY"),
|
||||
TokenKind::StringLiteral(text) => write!(f, r#"STRING_LITERAL("{}")"#, text),
|
||||
|
||||
TokenKind::CurlyBracketOpen => f.write_str("CURLY_BRACKET_OPEN"),
|
||||
|
@ -244,6 +236,8 @@ impl Display for TokenKind {
|
|||
TokenKind::AngledBracketClose => f.write_str("ANGLED_BRACKET_CLOSE"),
|
||||
TokenKind::SquareBracketOpen => f.write_str("SQUARE_BRACKET_OPEN"),
|
||||
TokenKind::SquareBracketClose => f.write_str("SQUARE_BRACKET_CLOSE"),
|
||||
|
||||
TokenKind::DefaultTokenKind => f.write_str("DEFAULT_TOKEN_KIND"),
|
||||
TokenKind::Comment(text) => write!(f, "COMMENT({})", text),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,16 @@ pub enum ParsingError {
|
|||
specified: Attribute,
|
||||
span: TokenSpan,
|
||||
},
|
||||
#[error("The structure named: {structure} has been used multiple times")]
|
||||
StructureCopied {
|
||||
structure: Identifier,
|
||||
span: TokenSpan,
|
||||
},
|
||||
#[error("The enumeration named: {enumeration} has been used multiple times")]
|
||||
EnumerationCopied {
|
||||
enumeration: Identifier,
|
||||
span: TokenSpan,
|
||||
},
|
||||
}
|
||||
|
||||
impl ParsingError {
|
||||
|
@ -80,6 +90,8 @@ impl ParsingError {
|
|||
ParsingError::NotEnoughGenericArgs { span, .. } => span,
|
||||
ParsingError::TooManyGenericArgs { span, .. } => span,
|
||||
ParsingError::WrongAttributeInPosition { span, .. } => span,
|
||||
ParsingError::StructureCopied { span, .. } => span,
|
||||
ParsingError::EnumerationCopied { span, .. } => span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +106,8 @@ impl AdditionalHelp for ParsingError {
|
|||
ParsingError::NotEnoughGenericArgs { got, expected_min, .. } => format!("Add generic args until you have gone from {} to {}", got, expected_min),
|
||||
ParsingError::TooManyGenericArgs { got, expected_max, .. } => format!("Remove generic args until you have gone from {} to {}", got, expected_max),
|
||||
ParsingError::WrongAttributeInPosition { .. } => format!("Remove this attribute"),
|
||||
ParsingError::StructureCopied {..} => format!("Change this name to be something else, or delete the struct"),
|
||||
ParsingError::EnumerationCopied {..} => format!("Change this name to be something else, or delete the enum"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,8 @@ impl Parser {
|
|||
fn parse(mut self) -> Result<CommandSpec, SpannedParsingError> {
|
||||
let namespace: UncheckedNamespace =
|
||||
UncheckedNamespace::from(mem::take(&mut self.command_spec));
|
||||
let namespace = self.process_namespace(namespace).map_err(|err| {
|
||||
|
||||
let namespace = self.process_namespace(namespace, vec![]).map_err(|err| {
|
||||
let span = *err.span();
|
||||
SpannedParsingError {
|
||||
source: Box::new(err),
|
||||
|
@ -119,6 +120,7 @@ impl Parser {
|
|||
fn process_namespace(
|
||||
&mut self,
|
||||
namespace: UncheckedNamespace,
|
||||
previous_namespaces: Vec<Identifier>,
|
||||
) -> Result<Namespace, ParsingError> {
|
||||
let namespace_span = namespace.name.span;
|
||||
let name = match namespace.name.kind {
|
||||
|
@ -126,24 +128,33 @@ impl Parser {
|
|||
name: ident,
|
||||
variant: Variant::Namespace,
|
||||
},
|
||||
// This is not really used, so the value put here does not matter
|
||||
TokenKind::Dummy => Identifier {
|
||||
name: "".to_owned(),
|
||||
variant: Variant::Void,
|
||||
// This is the first (implicit) root namespace
|
||||
TokenKind::DefaultTokenKind => Identifier {
|
||||
name: "<root>".to_owned(),
|
||||
variant: Variant::RootNamespace,
|
||||
},
|
||||
_ => unreachable!("This should never be more than these two enum veriants"),
|
||||
};
|
||||
let previous_namespaces = previous_namespaces
|
||||
.into_iter()
|
||||
.chain(iter::once(name.clone()))
|
||||
.collect();
|
||||
|
||||
let mut enumerations = vec![];
|
||||
let mut enumerations_counter = 0;
|
||||
for enumeration in namespace.enumerations {
|
||||
enumerations.push(self.process_enumeration(enumeration, &name, namespace_span)?);
|
||||
enumerations.push(self.process_enumeration(
|
||||
enumeration,
|
||||
&name,
|
||||
namespace_span,
|
||||
&previous_namespaces,
|
||||
)?);
|
||||
enumerations_counter += 1;
|
||||
}
|
||||
let mut structures = vec![];
|
||||
let mut structures_counter = 0;
|
||||
for structure in namespace.structures {
|
||||
structures.push(self.process_structure(structure)?);
|
||||
structures.push(self.process_structure(structure, &previous_namespaces)?);
|
||||
structures_counter += 1;
|
||||
}
|
||||
|
||||
|
@ -153,7 +164,7 @@ impl Parser {
|
|||
}
|
||||
let mut namespaces = vec![];
|
||||
for namespace in namespace.namespaces {
|
||||
namespaces.push(self.process_namespace(namespace)?);
|
||||
namespaces.push(self.process_namespace(namespace, previous_namespaces.clone())?);
|
||||
}
|
||||
|
||||
// Remove added enums and structs again
|
||||
|
@ -202,12 +213,15 @@ impl Parser {
|
|||
mut enumeration: UncheckedEnumeration,
|
||||
namespace_name: &Identifier,
|
||||
namespace_span: TokenSpan,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Enumeration, ParsingError> {
|
||||
self.enumerations.push(enumeration.clone());
|
||||
|
||||
let enum_span = enumeration.identifier.span;
|
||||
let identifier: Identifier =
|
||||
mem::take(&mut enumeration.identifier.kind).to_identifier(Variant::Enumeration);
|
||||
mem::take(&mut enumeration.identifier.kind).to_identifier(Variant::Enumeration {
|
||||
namespace: parent_namespaces.clone(),
|
||||
});
|
||||
if &identifier == namespace_name {
|
||||
return Err(ParsingError::EnumWithNamespaceName {
|
||||
name: identifier.clone(),
|
||||
|
@ -246,11 +260,14 @@ impl Parser {
|
|||
fn process_structure(
|
||||
&mut self,
|
||||
mut structure: UncheckedStructure,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Structure, ParsingError> {
|
||||
self.structures.push(structure.clone());
|
||||
|
||||
let identifier: Identifier =
|
||||
mem::take(&mut structure.identifier.kind).to_identifier(Variant::Structure);
|
||||
mem::take(&mut structure.identifier.kind).to_identifier(Variant::Structure {
|
||||
namespace: parent_namespaces.clone(),
|
||||
});
|
||||
let mut contents = vec![];
|
||||
for named_type in structure.contents {
|
||||
contents.push(self.process_doc_named_type(named_type)?);
|
||||
|
|
|
@ -33,7 +33,7 @@ fn test_full() {
|
|||
let input = "
|
||||
mod trinitrix {
|
||||
struct Callback {
|
||||
func: void,
|
||||
func: u32,
|
||||
timeout: u8,
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ mod trinitrix {
|
|||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "Callback".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Structure,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -90,7 +90,7 @@ mod trinitrix {
|
|||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "CallbackPriority".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Enumeration,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -112,8 +112,8 @@ mod trinitrix {
|
|||
},
|
||||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "()".to_owned(),
|
||||
variant: Variant::Type,
|
||||
name: "u32".to_owned(),
|
||||
variant: Variant::Primitive,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -127,7 +127,7 @@ mod trinitrix {
|
|||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "u8".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Primitive,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -188,8 +188,8 @@ fn execute_callback(callback: Name);
|
|||
assert_eq!(
|
||||
r#type,
|
||||
Identifier {
|
||||
name: "Name".to_owned(),
|
||||
variant: Variant::Type,
|
||||
name: "void".to_owned(),
|
||||
variant: Variant::Void,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ mod trinitrix {
|
|||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "String".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Primitive,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -256,7 +256,7 @@ mod trinitrix {
|
|||
r#type: Type {
|
||||
identifier: Identifier {
|
||||
name: "String".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Primitive,
|
||||
},
|
||||
generic_args: vec![],
|
||||
},
|
||||
|
@ -264,7 +264,7 @@ mod trinitrix {
|
|||
output: Some(Type {
|
||||
identifier: Identifier {
|
||||
name: "String".to_owned(),
|
||||
variant: Variant::Type,
|
||||
variant: Variant::Primitive,
|
||||
},
|
||||
generic_args: vec![],
|
||||
}),
|
||||
|
|
|
@ -63,7 +63,7 @@ impl Parser {
|
|||
fn parse(&mut self) -> Result<CommandSpec, SpannedParsingError> {
|
||||
let mut output = CommandSpec::default();
|
||||
while !self.token_stream.is_empty() {
|
||||
let next = self.parse_next().map_err(|err| {
|
||||
let next = self.parse_next(&vec![]).map_err(|err| {
|
||||
let span = err.get_span();
|
||||
SpannedParsingError {
|
||||
source: Box::new(err),
|
||||
|
@ -81,14 +81,20 @@ impl Parser {
|
|||
Ok(output)
|
||||
}
|
||||
|
||||
fn parse_next(&mut self) -> Result<Declaration, ParsingError> {
|
||||
fn parse_next(&mut self, current_namespaces: &Vec<Token>) -> Result<Declaration, ParsingError> {
|
||||
// Use of [peek_raw] here is fine, as we know that the function is only called, when
|
||||
// something should still be contained in the token stream
|
||||
match self.peek_raw().kind() {
|
||||
token![mod] => Ok(Declaration::Namespace(self.parse_namespace()?)),
|
||||
token![mod] => Ok(Declaration::Namespace(
|
||||
self.parse_namespace(current_namespaces.to_owned())?,
|
||||
)),
|
||||
token![fn] => Ok(Declaration::Function(self.parse_function()?)),
|
||||
token![struct] => Ok(Declaration::Structure(self.parse_structure()?)),
|
||||
token![enum] => Ok(Declaration::Enumeration(self.parse_enumeration()?)),
|
||||
token![struct] => Ok(Declaration::Structure(
|
||||
self.parse_structure(current_namespaces.clone())?,
|
||||
)),
|
||||
token![enum] => Ok(Declaration::Enumeration(
|
||||
self.parse_enumeration(current_namespaces.to_owned())?,
|
||||
)),
|
||||
token![#] => {
|
||||
let attributes = self.parse_attributes()?;
|
||||
self.current_attributes.extend(attributes);
|
||||
|
@ -107,7 +113,7 @@ impl Parser {
|
|||
span,
|
||||
})
|
||||
} else {
|
||||
self.parse_next()
|
||||
self.parse_next(current_namespaces)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -239,7 +245,10 @@ impl Parser {
|
|||
Ok(attrs)
|
||||
}
|
||||
|
||||
fn parse_namespace(&mut self) -> Result<Namespace, ParsingError> {
|
||||
fn parse_namespace(
|
||||
&mut self,
|
||||
previous_namespaces: Vec<Token>,
|
||||
) -> Result<Namespace, ParsingError> {
|
||||
let attributes = self.parse_attributes()?;
|
||||
self.expect(token![mod])?;
|
||||
|
||||
|
@ -248,11 +257,15 @@ impl Parser {
|
|||
attributes,
|
||||
..Default::default()
|
||||
};
|
||||
let current_namespaces: Vec<_> = previous_namespaces
|
||||
.into_iter()
|
||||
.chain(once(namespace.name.clone()))
|
||||
.collect();
|
||||
|
||||
self.expect(token![CurlyBracketOpen])?;
|
||||
|
||||
while !self.expect_peek(token![CurlyBracketClose]) {
|
||||
let next = self.parse_next()?;
|
||||
let next = self.parse_next(¤t_namespaces)?;
|
||||
match next {
|
||||
Declaration::Function(function) => namespace.functions.push(function),
|
||||
Declaration::Structure(structure) => namespace.structures.push(structure),
|
||||
|
@ -267,7 +280,10 @@ impl Parser {
|
|||
Ok(namespace)
|
||||
}
|
||||
|
||||
fn parse_enumeration(&mut self) -> Result<Enumeration, ParsingError> {
|
||||
fn parse_enumeration(
|
||||
&mut self,
|
||||
current_namespaces: Vec<Token>,
|
||||
) -> Result<Enumeration, ParsingError> {
|
||||
let attributes = self.parse_attributes()?;
|
||||
self.expect(token![enum])?;
|
||||
let identifier = self.expect(token![Ident])?;
|
||||
|
@ -299,10 +315,14 @@ impl Parser {
|
|||
identifier,
|
||||
states,
|
||||
attributes,
|
||||
namespaces: current_namespaces,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_structure(&mut self) -> Result<Structure, ParsingError> {
|
||||
fn parse_structure(
|
||||
&mut self,
|
||||
current_namespaces: Vec<Token>,
|
||||
) -> Result<Structure, ParsingError> {
|
||||
let attributes = self.parse_attributes()?;
|
||||
self.expect(token![struct])?;
|
||||
let name = self.expect(token![Ident])?;
|
||||
|
@ -326,6 +346,7 @@ impl Parser {
|
|||
identifier: name,
|
||||
contents,
|
||||
attributes,
|
||||
namespaces: current_namespaces,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue