use std::{iter::once, mem};
use crate::{
parser::{
command_spec::unchecked::{
Attribute, CommandSpec, Declaration, DeriveValue, DocNamedType, DocToken, Enumeration,
Function, NamedType, Namespace, StringLiteral, Structure, Type,
},
error::ErrorContext,
lexing::{AttributeKeyword, Token, TokenKind, TokenSpan, TokenStream},
},
token,
};
use self::error::{ParsingError, SpannedParsingError};
pub mod error;
impl TokenStream {
pub fn parse_unchecked(self) -> Result<CommandSpec, SpannedParsingError> {
let mut parser = Parser::new(self);
parser.parse()
}
}
pub(super) struct Parser {
token_stream: TokenStream,
current_attributes: Vec<Attribute>,
last_span: TokenSpan,
}
impl Parser {
fn new(mut token_stream: TokenStream) -> Self {
token_stream.reverse();
Self {
token_stream,
current_attributes: vec![],
last_span: TokenSpan::default(),
}
}
fn parse(&mut self) -> Result<CommandSpec, SpannedParsingError> {
let mut output = CommandSpec::default();
while !self.token_stream.is_empty() {
let next = self.parse_next(&vec![]).map_err(|err| {
let span = err.get_span();
SpannedParsingError {
source: Box::new(err),
context: ErrorContext::from_span(span, &self.token_stream.original_file),
}
})?;
match next {
Declaration::Function(function) => output.functions.push(function),
Declaration::Structure(structure) => output.structures.push(structure),
Declaration::Enumeration(enumeration) => output.enumerations.push(enumeration),
Declaration::Namespace(namespace) => output.namespaces.push(namespace),
}
}
Ok(output)
}
fn parse_next(&mut self, current_namespaces: &Vec<Token>) -> Result<Declaration, ParsingError> {
match self.peek_raw().kind() {
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(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);
if self.token_stream.is_empty() {
fn get_span(attr: Option<&Attribute>) -> TokenSpan {
attr.expect("Something should be here").span()
}
let span = TokenSpan::from_range(
get_span(self.current_attributes.first()),
get_span(self.current_attributes.last()),
);
Err(ParsingError::TrailingAttribute {
comments: mem::take(&mut self.current_attributes),
span,
})
} else {
self.parse_next(current_namespaces)
}
}
_ => {
let err = ParsingError::ExpectedKeyword {
span: *self.peek_raw().span(),
actual: self.peek_raw().kind().clone(),
};
Err(err)
}
}
}
fn parse_type(&mut self) -> Result<Type, ParsingError> {
if self.expect_peek(token![Ident]) {
let identifier = self.expect(token![Ident])?;
let mut generic_args = vec![];
if self.expect_peek(token![<]) {
self.expect(token![<])?;
if self.expect_peek(token![Ident]) {
generic_args.push(self.parse_type()?);
}
while self.expect_peek(token![Comma]) {
self.expect(token![Comma])?;
generic_args.push(self.parse_type()?);
}
self.expect(token![>])?;
}
Ok(Type::Typical {
identifier,
generic_args,
})
} else {
self.expect(token![fn])?;
self.expect(token![CurvedBracketOpen])?;
let mut inputs = vec![];
if self.expect_peek(token![Ident]) {
inputs.push(self.parse_named_type()?);
}
while self.expect_peek(token![Comma]) {
self.expect(token![Comma])?;
inputs.push(self.parse_named_type()?);
}
self.expect(token![CurvedBracketClose])?;
let mut output_type = None;
if self.expect_peek(token![->]) {
self.expect(token![->])?;
output_type = Some(Box::new(self.parse_type()?));
}
Ok(Type::Function {
inputs,
output: output_type,
})
}
}
fn parse_attribute_value(&mut self) -> Result<Attribute, ParsingError> {
let ident = self.expect(token![AttributeKeyword])?;
let span = *ident.span();
let TokenKind::AttributeKeyword(keyword) = ident.kind() else {
unreachable!("This is checked in the `expect` above")
};
let attribute = match keyword {
AttributeKeyword::derive => {
self.expect(token![CurvedBracketOpen])?;
let string_literal_token = self.expect(token![Identifier])?;
let string_literal =
if let TokenKind::Identifier(ident) = string_literal_token.kind() {
ident
} else {
unreachable! {"The token is a identifier, as checked by the `expect`"};
};
self.expect(token![CurvedBracketClose])?;
match string_literal.as_str() {
"Error" => Ok(Attribute::derive {
value: DeriveValue::Error,
span,
}),
_ => Err(error::ParsingError::WrongDeriveValue {
specified: StringLiteral {
content: string_literal.to_owned(),
span: string_literal_token.span,
},
}),
}
}
AttributeKeyword::doc => {
self.expect(token![=])?;
let string_literal = self.expect(token![StringLiteral])?;
let string_literal = Into::<StringLiteral>::into(string_literal);
Ok(Attribute::doc {
content: string_literal,
span,
})
}
AttributeKeyword::error => {
self.expect(token![=])?;
let string_literal = self.expect(token![StringLiteral])?;
let string_literal = Into::<StringLiteral>::into(string_literal);
Ok(Attribute::error {
content: string_literal,
span,
})
}
}?;
Ok(attribute)
}
fn parse_attributes(&mut self) -> Result<Vec<Attribute>, ParsingError> {
let mut attrs = mem::take(&mut self.current_attributes);
while self.expect_peek(token![#]) {
attrs.push({
self.expect(token![#])?;
self.expect(token![SquareBracketOpen])?;
let attribue = self.parse_attribute_value()?;
self.expect(token![SquareBracketClose])?;
attribue
});
}
Ok(attrs)
}
fn parse_namespace(
&mut self,
previous_namespaces: Vec<Token>,
) -> Result<Namespace, ParsingError> {
let attributes = self.parse_attributes()?;
self.expect(token![mod])?;
let mut namespace = Namespace {
name: self.expect(token![Ident])?,
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(¤t_namespaces)?;
match next {
Declaration::Function(function) => namespace.functions.push(function),
Declaration::Structure(structure) => namespace.structures.push(structure),
Declaration::Enumeration(enumeration) => namespace.enumerations.push(enumeration),
Declaration::Namespace(input_namespace) => {
namespace.namespaces.push(input_namespace)
}
}
}
self.expect(token![CurlyBracketClose])?;
Ok(namespace)
}
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])?;
self.expect(token![CurlyBracketOpen])?;
let mut states = vec![];
if self.expect_peek(token![Ident]) || self.expect_peek(token![#]) {
let attributes = self.parse_attributes()?;
states.push(DocToken {
token: self.expect(token![Ident])?,
attributes,
});
while self.expect_peek(token![Comma]) {
self.expect(token![Comma])?;
if self.expect_peek(token![Ident]) || self.expect_peek(token![#]) {
let attributes = self.parse_attributes()?;
states.push(DocToken {
token: self.expect(token![Ident])?,
attributes,
});
} else {
break;
}
}
}
self.expect(token![CurlyBracketClose])?;
Ok(Enumeration {
identifier,
states,
attributes,
namespaces: current_namespaces,
})
}
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])?;
self.expect(token![CurlyBracketOpen])?;
let mut contents = vec![];
if self.expect_peek(token![Ident]) || self.expect_peek(token![#]) {
contents.push(self.parse_doc_named_type()?);
}
while self.expect_peek(token![Comma]) {
self.expect(token![Comma])?;
if self.expect_peek(token![Ident]) || self.expect_peek(token![PoundSign]) {
contents.push(self.parse_doc_named_type()?);
} else {
break;
}
}
self.expect(token![CurlyBracketClose])?;
Ok(Structure {
identifier: name,
contents,
attributes,
namespaces: current_namespaces,
})
}
fn parse_named_type(&mut self) -> Result<NamedType, ParsingError> {
let name = self.expect(token![Ident])?;
self.expect(token![Colon])?;
let r#type = self.parse_type()?;
Ok(NamedType { name, r#type })
}
fn parse_doc_named_type(&mut self) -> Result<DocNamedType, ParsingError> {
let attributes = self.parse_attributes()?;
let name = self.expect(token![Ident])?;
self.expect(token![Colon])?;
let r#type = self.parse_type()?;
Ok(DocNamedType {
name,
r#type,
attributes,
})
}
fn parse_function(&mut self) -> Result<Function, ParsingError> {
let attributes = self.parse_attributes()?;
self.expect(token![fn])?;
let name = self.expect(token![Ident])?;
self.expect(token![CurvedBracketOpen])?;
let mut inputs = vec![];
if self.expect_peek(token![Ident]) {
inputs.push(self.parse_named_type()?);
}
while self.expect_peek(token![Comma]) {
self.expect(token![Comma])?;
inputs.push(self.parse_named_type()?);
}
self.expect(token![CurvedBracketClose])?;
let mut output_type = None;
if self.expect_peek(token![->]) {
self.expect(token![->])?;
output_type = Some(self.parse_type()?);
}
self.expect(token![;])?;
Ok(Function {
identifier: name,
inputs,
output: output_type,
attributes,
})
}
pub(super) fn expect(&mut self, token: TokenKind) -> Result<Token, ParsingError> {
let actual_token = if let Some(token) = self.peek() {
token
} else {
return Err(ParsingError::UnexpectedEOF {
expected: token,
span: self.last_span,
});
};
if actual_token.kind().same_kind(&token) {
Ok(self.pop())
} else {
let err = ParsingError::ExpectedDifferentToken {
expected: token,
actual: actual_token.kind().clone(),
span: *actual_token.span(),
};
Err(err)
}
}
fn expect_peek(&self, token: TokenKind) -> bool {
let actual_token = match self.peek() {
Some(ok) => ok,
None => return false,
};
actual_token.kind().same_kind(&token)
}
fn peek(&self) -> Option<&Token> {
self.token_stream.peek()
}
fn peek_raw(&self) -> &Token {
self.token_stream.peek().expect("The token should exist")
}
fn pop(&mut self) -> Token {
self.last_span = *self
.peek()
.expect("Calling pop should mean, that a token was first peeked for")
.span();
self.token_stream.pop()
}
}