use crate::{ ast::err::ParseError, ast::types::{ ArrayDimension, CompileUnit, Expr, FuncDeclStmt, GlobalDeclStmt, Param, StorageClass, VarDeclStmt, VarDeclStmtValue, }, diagnostic::span::Span, lexer::types::{TokenValue, TypeIdent}, }; use super::{ParseProcessError, ParseType, Parser}; struct DeclSpecifiers { storage_class: Option, type_specifier: TypeIdent, type_span: Span, } struct Declarator { name: String, name_span: Span, suffixes: Vec, } enum DeclaratorSuffix { Array(ArrayDimension), Function { params: Vec, span: Span, }, } struct InitDeclarator { declarator: Declarator, initializer: Option, } impl Parser { pub(super) fn parse_compile_unit(&mut self) -> CompileUnit { let mut global_decls = vec![]; while !self.is_eof() { if let Some(decl) = self.parse_external_decl_stmt() { global_decls.push(decl); } else { self.until_next_token(&[TokenValue::Semicolon, TokenValue::RBrace]); } } CompileUnit { global_decls } } fn parse_external_decl_stmt(&mut self) -> Option { let specifiers = match self.parse_decl_specifiers(ParseType::MustParse) { Ok(specifiers) => specifiers, Err(ParseProcessError::ErrorInMatch) => return None, Err(ParseProcessError::TryNext) => unreachable!(), }; let declarator = match self.parse_declarator() { Ok(declarator) => declarator, Err(ParseProcessError::ErrorInMatch) => return None, Err(ParseProcessError::TryNext) => unreachable!(), }; if self.peek().value == TokenValue::LBrace { match self.finish_func_def_stmt(specifiers, declarator) { Ok(func_decl) => return Some(GlobalDeclStmt::FuncDecl(func_decl)), Err(ParseProcessError::ErrorInMatch) => return None, Err(ParseProcessError::TryNext) => unreachable!(), } } match self.finish_var_decl_stmt(specifiers, declarator, true, true) { Ok(var_decl) => Some(GlobalDeclStmt::VarDecl(var_decl)), Err(ParseProcessError::ErrorInMatch) => None, Err(ParseProcessError::TryNext) => unreachable!(), } } fn parse_decl_specifiers( &mut self, parse_type: ParseType, ) -> Result { let storage_class = if self.peek().value == TokenValue::Static { self.advance(1); Some(StorageClass::Static) } else { None }; let type_token = self.peek().clone(); let type_specifier = match type_token.value.as_type_ident() { Some(type_specifier) => { self.advance(1); type_specifier } None if parse_type == ParseType::TryParse && storage_class.is_none() => { return Err(ParseProcessError::TryNext); } None => { let token = self.next(); self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(token.value, "type specifier"), token.span, ); return Err(ParseProcessError::ErrorInMatch); } }; Ok(DeclSpecifiers { storage_class, type_specifier, type_span: type_token.span, }) } fn parse_declarator(&mut self) -> Result { self.parse_direct_declarator() } fn parse_direct_declarator(&mut self) -> Result { let mut declarator = match self.peek().value.clone() { TokenValue::Ident(name) => { let name_span = self.peek().span; self.advance(1); Declarator { name, name_span, suffixes: vec![], } } TokenValue::LParen => { self.advance(1); let declarator = self.parse_declarator()?; self.must_match_token(&TokenValue::RParen, "`)`")?; declarator } _ => { let token = self.next(); self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(token.value, "declarator"), token.span, ); return Err(ParseProcessError::ErrorInMatch); } }; loop { match self.peek().value { TokenValue::LBracket => { let dimension = self.parse_array_declarator_suffix()?; declarator.suffixes.push(DeclaratorSuffix::Array(dimension)); } TokenValue::LParen => { let start_span = self.next().span; let params = self.parse_parameter_list_after_lparen()?; let end_span = self.last().span; declarator.suffixes.push(DeclaratorSuffix::Function { params, span: Span::from_two(start_span, end_span), }); } _ => break, } } Ok(declarator) } fn parse_array_declarator_suffix(&mut self) -> Result { let start_span = self.next().span; let value = if self.peek().value == TokenValue::RBracket { None } else { Some(self.parse_expr()?) }; let end_span = match &self.peek().value { TokenValue::RBracket => { let span = self.peek().span; self.advance(1); span } // TokenValue::Eof => { // self.diagnostics.add_from_frontend_error( // ParseError::ExpectedBefore(TokenValue::Eof, "`]`"), // start_span, // ); // return Err(ParseProcessError::ErrorInMatch); // } _ => { let token = self.next(); self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(token.value, "`]`"), token.span, ); return Err(ParseProcessError::ErrorInMatch); } }; Ok(ArrayDimension { value, span: Span::from_two(start_span, end_span), }) } fn parse_parameter_list_after_lparen(&mut self) -> Result, ParseProcessError> { if self.peek().value == TokenValue::RParen { self.advance(1); return Ok(vec![]); } let mut params = vec![]; loop { match self.parse_param() { Ok(param) => params.push(param), Err(error) => { self.until_next_token(&[TokenValue::Comma, TokenValue::RParen]); if self.last().value == TokenValue::RParen { return Err(error); } continue; } } match self.peek().value { TokenValue::Comma => { self.advance(1); } TokenValue::RParen => { self.advance(1); break; } _ => { self.must_match_token(&TokenValue::RParen, "`,` or `)`")?; break; } } } Ok(params) } fn parse_param(&mut self) -> Result { let specifiers = self.parse_decl_specifiers(ParseType::MustParse)?; let declarator = self.parse_declarator()?; self.declarator_to_param(specifiers, declarator) } pub(super) fn parse_var_decl_stmt( &mut self, parse_type: ParseType, ) -> Result { self.parse_var_decl_stmt_inner(parse_type, true) } pub(super) fn parse_var_decl_stmt_inner( &mut self, parse_type: ParseType, consume_semicolon: bool, ) -> Result { let specifiers = self.parse_decl_specifiers(parse_type)?; let declarator = self.parse_declarator()?; self.finish_var_decl_stmt(specifiers, declarator, consume_semicolon, false) } fn finish_func_def_stmt( &mut self, specifiers: DeclSpecifiers, declarator: Declarator, ) -> Result { let Declarator { name, name_span, suffixes, } = declarator; let params = self.take_function_params(name_span, suffixes)?; let body = self.parse_block_stmt(ParseType::MustParse)?; Ok(FuncDeclStmt { return_type: specifiers.type_specifier.into(), storage_class: specifiers.storage_class, name, params, body, ret_type_span: specifiers.type_span, name_span, }) } fn finish_var_decl_stmt( &mut self, specifiers: DeclSpecifiers, first_declarator: Declarator, consume_semicolon: bool, _allow_empty_declarator_list: bool, ) -> Result { let mut values = vec![]; let initializer = self.parse_initializer()?; values.push(self.init_declarator_to_var_value(InitDeclarator { declarator: first_declarator, initializer, })?); while self.peek().value == TokenValue::Comma { self.advance(1); let declarator = self.parse_declarator()?; let initializer = self.parse_initializer()?; values.push(self.init_declarator_to_var_value(InitDeclarator { declarator, initializer, })?); } if consume_semicolon { self.must_match_token(&TokenValue::Semicolon, "`;`")?; } Ok(VarDeclStmt { storage_class: specifiers.storage_class, values, type_span: specifiers.type_span, data_type: specifiers.type_specifier.into(), }) } fn parse_initializer(&mut self) -> Result, ParseProcessError> { if self.peek().value != TokenValue::Equal { return Ok(None); } self.advance(1); Ok(Some(self.parse_expr()?)) } fn init_declarator_to_var_value( &mut self, init_declarator: InitDeclarator, ) -> Result { let Declarator { name, name_span, suffixes, } = init_declarator.declarator; let dimensions = self.take_array_dimensions(suffixes)?; Ok(VarDeclStmtValue { name, name_span, dimensions, value: init_declarator.initializer, }) } fn declarator_to_param( &mut self, specifiers: DeclSpecifiers, declarator: Declarator, ) -> Result { let Declarator { name, name_span, suffixes, } = declarator; let dimensions = self.take_array_dimensions(suffixes)?; Ok(Param { param_type: specifiers.type_specifier.into(), name, dimensions, name_span, type_span: specifiers.type_span, }) } fn take_array_dimensions( &mut self, suffixes: Vec, ) -> Result, ParseProcessError> { let mut dimensions = vec![]; for suffix in suffixes { match suffix { DeclaratorSuffix::Array(dimension) => dimensions.push(dimension), DeclaratorSuffix::Function { span, .. } => { self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(TokenValue::LParen, "variable declarator"), span, ); return Err(ParseProcessError::ErrorInMatch); } } } Ok(dimensions) } fn take_function_params( &mut self, name_span: Span, suffixes: Vec, ) -> Result, ParseProcessError> { let mut params = None; for suffix in suffixes { match suffix { DeclaratorSuffix::Function { params: suffix_params, .. } if params.is_none() => params = Some(suffix_params), DeclaratorSuffix::Function { span, .. } => { self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(TokenValue::LParen, "function body"), span, ); return Err(ParseProcessError::ErrorInMatch); } DeclaratorSuffix::Array(dimension) => { self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(TokenValue::LBracket, "function declarator"), dimension.span, ); return Err(ParseProcessError::ErrorInMatch); } } } match params { Some(params) => Ok(params), None => { self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(TokenValue::LBrace, "function declarator"), name_span, ); Err(ParseProcessError::ErrorInMatch) } } } }