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:
Benedikt Peetz 2024-03-24 19:57:32 +01:00
parent 4a32f0d2f4
commit 3c3ee23c2b
Signed by: bpeetz
GPG Key ID: A5E94010C3A642AD
7 changed files with 104 additions and 48 deletions

View File

@ -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(),
}
}
}

View File

@ -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)]

View File

@ -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),
}
}

View File

@ -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"),
}
}
}

View File

@ -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)?);

View File

@ -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![],
}),

View File

@ -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(&current_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,
})
}