diff --git a/parser/src/ast.rs b/parser/src/ast.rs index a162f0c..bc7db38 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -23,3 +23,16 @@ pub enum TypeSpecifier { // enum-specifier // typedef-name } + +#[derive(Debug, Default, DebugPls)] +pub struct DeclAttr { + pub is_extern: bool, + pub is_static: bool, + pub is_thread_local: bool, +} + +#[derive(Debug, DebugPls)] +pub struct DeclSpec { + pub ty: TypeSpecifier, + pub attrs: DeclAttr, +} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e65cf86..8d55b85 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -6,7 +6,21 @@ mod parser; mod pre; mod token; -pub type Span = std::ops::Range; +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +pub struct Span { + pub start: usize, + pub end: usize, +} + +impl Span { + pub fn start_end(start: usize, end: usize) -> Self { + Self { start, end } + } + + pub fn extend(&self, rhs: Self) -> Self { + Self::start_end(self.start, rhs.end) + } +} pub fn parse_file(src: &str) { println!("{src}"); diff --git a/parser/src/parser.rs b/parser/src/parser.rs index bd62903..0ca4b01 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -1,7 +1,7 @@ use peekmore::PeekMoreIterator; use crate::{ - ast::{Spanned, TypeSpecifier}, + ast::{DeclAttr, DeclSpec, Spanned, TypeSpecifier}, token::{Keyword as Kw, Token as Tok}, Span, }; @@ -17,7 +17,11 @@ impl ParserError { } fn eof() -> Self { - Self::new(0..0, "unexpected end of file".to_string()) + Self::new(Span::default(), "unexpected end of file".to_string()) + } + + fn unsupported(span: Span, token: &Tok<'_>) -> Self { + Self::new(span, format!("`{token}` is not supported")) } } @@ -34,6 +38,86 @@ impl<'src, I> Parser<'src, I> where I: Iterator, Span)>, { + fn find_typedef(&self, ident: &str) -> Option<()> { + None // TODO: this + } + + fn next_t(&mut self) -> Result<(Tok<'src>, Span)> { + self.lex.next().ok_or_else(ParserError::eof) + } + + fn peek_t(&mut self) -> Result<&(Tok<'src>, Span)> { + self.lex.peek().ok_or_else(ParserError::eof) + } + + // ----------------------- + // Declarations + // ----------------------- + + /// (6.7) declaration: + /// declaration-specifiers init-declarator-listopt ; + /// static_assert-declaration + fn declaration(&mut self) -> Result> { + todo!() + } + + /// (6.7) declaration-specifiers: + /// storage-class-specifier declaration-specifiers.opt + /// type-specifier declaration-specifiers.opt + /// type-qualifier declaration-specifiers.opt + /// function-specifier declaration-specifiers.opt + /// alignment-specifier declaration-specifiers.opt + fn declaration_specifiers(&mut self) -> Result> { + let mut decl_attr = DeclAttr::default(); + let &(_, initial_span) = self.peek_t()?; + let (ty, span) = loop { + match self.peek_t()?.0 { + // (6.7.1) storage-class-specifier + Tok::Kw(Kw::Typedef | Kw::Auto | Kw::Register) => { + self.next_t()?; // ignore + } + Tok::Kw(Kw::Extern) => { + self.next_t()?; + decl_attr.is_extern = true; + } + Tok::Kw(Kw::Static) => { + self.next_t()?; + decl_attr.is_static = true; + } + Tok::Kw(Kw::ThreadLocal) => { + self.next_t()?; + decl_attr.is_thread_local = true; + } + // (6.7.3) type-qualifier: + Tok::Kw(Kw::Const | Kw::Restrict | Kw::Volatile | Kw::Atomic) => { + self.next_t()?; // ignore + } + // (6.7.4) function-specifier: + Tok::Kw(Kw::Inline | Kw::Noreturn) => { + self.next_t()?; // ignore + } + // (6.7.5) alignment-specifier: + Tok::Kw(Kw::Alignas) => { + let (token, span) = self.next_t()?; + return Err(ParserError::unsupported(span, &token)); + } + // if it's neither of the above, it has to be a type-specifier + _ => { + let ty = self.type_specifier()?; + break ty; + } + } + }; + + Ok(( + DeclSpec { + ty, + attrs: decl_attr, + }, + initial_span.extend(span), + )) + } + fn type_specifier(&mut self) -> Result> { let (token, span) = self.next_t()?; let ty = match token { @@ -47,13 +131,43 @@ where Tok::Kw(Kw::Signed) => TypeSpecifier::Signed, Tok::Kw(Kw::Unsigned) => TypeSpecifier::Unsigned, Tok::Kw(Kw::Bool) => TypeSpecifier::Bool, - Tok::Kw(Kw::Complex) => return Err(ParserError::new(span, "tf are you doing with complex numbers".to_string())), + Tok::Kw(Kw::Complex) => { + return Err(ParserError::new( + span, + "tf are you doing with complex numbers".to_string(), + )) + } tok => return Err(ParserError::new(span, format!("Invalid token: `{tok}`"))), }; Ok((ty, span)) } - fn next_t(&mut self) -> Result<(Tok<'src>, Span)> { - self.lex.next().ok_or_else(ParserError::eof) + // ----------------------- + // External definitions + // ----------------------- + + + /// (6.9) external-declaration: + /// function-definition + /// declaration + fn external_declaration(&mut self) -> Result<()> { + let (next, span) = self.peek_t()?; + if let Tok::Kw(Kw::StaticAssert) = next { + return Err(ParserError::unsupported(*span, next)); + } + + let decl_spec = self.declaration_specifiers()?; + + // TODO: We just assume that it's a function, that's terrible! + + self.function_definition(decl_spec)?; + + todo!() + } + + /// (6.9.1) function-definition: + /// declaration-specifiers declarator declaration-list.opt compound-statement + fn function_definition(&mut self, specifiers: Spanned) -> Result> { + todo!() } } diff --git a/parser/src/pre/lexer.rs b/parser/src/pre/lexer.rs index 398b3bd..603959c 100644 --- a/parser/src/pre/lexer.rs +++ b/parser/src/pre/lexer.rs @@ -3,7 +3,7 @@ //! //! Code might be bad. Possibly. -use std::{ops::Not, fmt::Display}; +use std::{fmt::Display, ops::Not}; use peekmore::PeekMore; @@ -398,11 +398,11 @@ where } }; - Some((token, start_span..end_span + 1)) + Some((token, Span::start_end(start_span, end_span + 1))) } } -pub fn preprocess_tokens(src: &str) -> impl Iterator, std::ops::Range)> { +pub fn preprocess_tokens(src: &str) -> impl Iterator, Span)> { let lexer = PLexer { src_str: src, src: src.bytes().enumerate().peekmore(),