From 908c5c7615725c04c662088986ace075c385cf3b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 25 Jun 2022 17:49:14 +0200 Subject: [PATCH] i declare victory (not) --- .gitignore | 2 + parser/src/ast.rs | 33 +++++--- parser/src/parser.rs | 75 ++++++++++++++++--- .../parser__token__tests__hello_world.snap | 4 +- parser/src/token.rs | 6 +- 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..2674b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +.idea +.vscode \ No newline at end of file diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 921ba30..2a5eb42 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -24,6 +24,8 @@ pub enum TypeSpecifier { // typedef-name } +pub type Ident = Spanned; + #[derive(Debug, Default, DebugPls)] pub struct DeclAttr { pub is_extern: bool, @@ -39,18 +41,29 @@ pub struct DeclSpec { #[derive(Debug, DebugPls)] pub enum Declaration { - Normal { - decl_spec: DeclSpec, - name: Option, - initializer: Option<()>, - pointer: bool, - }, + Normal(NormalDeclaration), StaticAssert, } +#[derive(Debug, DebugPls)] +pub struct NormalDeclaration { + pub decl_spec: DeclSpec, + pub declarator: Declarator, + pub initializer: Option<()>, +} + +#[derive(Debug, DebugPls)] +pub enum DirectDeclarator { + Ident(Ident), + WithParams { + ident: Ident, + params: Vec, + }, +} + #[derive(Debug, DebugPls)] pub struct Declarator { - pub identifier: String, + pub decl: DirectDeclarator, pub pointer: bool, } @@ -63,13 +76,13 @@ pub struct FunctionParamDecl { #[derive(Debug, DebugPls)] pub enum FunctionParameters { Void(Span), - List(Vec>), + List(Vec>), } #[derive(Debug, DebugPls)] pub struct FunctionDefinition { pub decl_spec: Spanned, - pub declarator: Spanned, - pub declaration_list: FunctionParameters, + pub name: Ident, + pub parameter_list: FunctionParameters, pub body: Vec<()>, } diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 06b677f..370e614 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -2,8 +2,8 @@ use peekmore::PeekMoreIterator; use crate::{ ast::{ - DeclAttr, DeclSpec, Declaration, Declarator, FunctionDefinition, FunctionParamDecl, - FunctionParameters, Spanned, TypeSpecifier, + DeclAttr, DeclSpec, Declaration, Declarator, DirectDeclarator, FunctionDefinition, + FunctionParamDecl, FunctionParameters, Ident, Spanned, TypeSpecifier, }, pre::Punctuator as Punct, token::{Keyword as Kw, Token as Tok}, @@ -56,6 +56,15 @@ macro_rules! expect { }; } +macro_rules! eat { + ($self:ident, $pat:pat) => { + match $self.peek_t() { + Ok(($pat, _)) => Some($self.next_t()?), + _ => None, + } + }; +} + /// Can be called for the start of a sequence of tokens that could be a type. #[rustfmt::skip] fn is_tok_start_of_ty(tok: &Tok<'_>) -> bool { @@ -75,7 +84,7 @@ fn is_tok_start_of_ty(tok: &Tok<'_>) -> bool { // function specifiers | Kw::Inline | Kw::Noreturn ) => true, - Tok::Identifier(_) => false, // TODO: lookup typedefs! + Tok::Ident(_) => false, // TODO: lookup typedefs! _ => false, } } @@ -104,9 +113,9 @@ where self.lex.peek_nth(n).ok_or_else(ParserError::eof) } - fn ident(&mut self) -> Result> { + fn ident(&mut self) -> Result { match self.next_t()? { - (Tok::Identifier(ident), span) => Ok((ident.to_string(), span)), + (Tok::Ident(ident), span) => Ok((ident.to_string(), span)), (tok, span) => Err(ParserError::new( span, format!("expected identifier, found `{tok}`"), @@ -232,7 +241,48 @@ where /// (6.7.6) declarator: /// pointer.opt direct-declarator + /// + /// It's only really known after the parsing of a declarator which kind of declaration we are + /// facing. For example: `int uwu` vs `int uwu()`. The parentheses indicate a function + /// declaration. Therefore, we have no idea what we're parsing before entering this function. fn declarator(&mut self) -> Result> { + if let Some((_, span)) = eat!(self, Tok::Punct(Punct::Asterisk)) { + let (decl, span2) = self.direct_declarator()?; + + Ok(( + Declarator { + decl, + pointer: true, + }, + span.extend(span2), + )) + } else { + let (decl, span) = self.direct_declarator()?; + + Ok(( + Declarator { + decl, + pointer: false, + }, + span, + )) + } + } + + /// direct-declarator: + /// identifier + /// ( declarator ) + /// direct-declarator \[ type-qualifier-listopt assignment-expressionopt ] + /// direct-declarator \[ static type-qualifier-listopt assignment-expression ] + /// direct-declarator \[ type-qualifier-list static assignment-expression ] + /// direct-declarator \[ type-qualifier-listopt * ] + /// direct-declarator ( parameter-type-list ) + /// direct-declarator ( identifier-listopt ) + fn direct_declarator(&mut self) -> Result> { + if let Some((Tok::Ident(name), span)) = eat!(self, Tok::Ident(_)) { + return Ok((DirectDeclarator::Ident((name.to_owned(), span)), span)); + } + todo!() } @@ -244,9 +294,8 @@ where /// 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)); + if let Some((token, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) { + return Err(ParserError::unsupported(span, &token)); } let decl_spec = self.declaration_specifiers()?; @@ -269,6 +318,8 @@ where &mut self, decl_spec: Spanned, ) -> Result> { + let _oh_fuck = self.declarator()?; + let declarator = self.ident()?; let decl_spec_span = decl_spec.1; @@ -283,8 +334,8 @@ where let def = FunctionDefinition { decl_spec, - declarator, - declaration_list, + name: declarator, + parameter_list: declaration_list, body: Vec::new(), }; @@ -300,6 +351,7 @@ where // shall follow. if let &(Tok::Kw(Kw::Void), span) = self.peek_t()? { if let (Tok::Punct(Punct::ParenClose), _) = self.peek_t_n(1)? { + self.next_t()?; self.next_t()?; return Ok(FunctionParameters::Void(span)); } @@ -328,10 +380,9 @@ where }; params.push((param, span1.extend(span2))); - } - Ok(FunctionParameters::List(params)) + Ok(FunctionParameters::List(todo!())) } } diff --git a/parser/src/snapshots/parser__token__tests__hello_world.snap b/parser/src/snapshots/parser__token__tests__hello_world.snap index 64966bb..09f98df 100644 --- a/parser/src/snapshots/parser__token__tests__hello_world.snap +++ b/parser/src/snapshots/parser__token__tests__hello_world.snap @@ -10,7 +10,7 @@ expression: tokens 1..4, ), ( - Identifier( + Ident( "main", ), 5..9, @@ -34,7 +34,7 @@ expression: tokens 12..13, ), ( - Identifier( + Ident( "puts", ), 18..22, diff --git a/parser/src/token.rs b/parser/src/token.rs index fa9f07c..8dbb010 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -14,7 +14,7 @@ use crate::{ #[derive(Debug, Clone, Copy)] pub enum Token<'src> { Kw(Keyword), - Identifier(&'src str), + Ident(&'src str), Constant(Constant), StringLiteral(&'src str), Punct(Punctuator), @@ -140,7 +140,7 @@ pub fn pre_tokens_to_tokens<'src>( PToken::HeaderName(_) => todo!("header names aren't real, wake up"), PToken::Identifier(ident) => match ident_to_keyword(ident) { Some(keyword) => Token::Kw(keyword), - None => Token::Identifier(ident), + None => Token::Ident(ident), }, PToken::PpNumber(number) => pp_number_to_constant(number) .map(Token::Constant) @@ -159,7 +159,7 @@ impl Display for Token<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Token::Kw(kw) => Display::fmt(kw, f), - Token::Identifier(ident) => Display::fmt(ident, f), + Token::Ident(ident) => Display::fmt(ident, f), Token::Constant(c) => Display::fmt(c, f), Token::StringLiteral(str) => write!(f, "\"{}\"", str), Token::Punct(p) => Display::fmt(p, f),