430 lines
14 KiB
Rust
430 lines
14 KiB
Rust
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<StorageClass>,
|
|
type_specifier: TypeIdent,
|
|
type_span: Span,
|
|
}
|
|
|
|
struct Declarator {
|
|
name: String,
|
|
name_span: Span,
|
|
suffixes: Vec<DeclaratorSuffix>,
|
|
}
|
|
|
|
enum DeclaratorSuffix {
|
|
Array(ArrayDimension),
|
|
Function {
|
|
params: Vec<Param>,
|
|
span: Span,
|
|
},
|
|
}
|
|
|
|
struct InitDeclarator {
|
|
declarator: Declarator,
|
|
initializer: Option<Expr>,
|
|
}
|
|
|
|
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<GlobalDeclStmt> {
|
|
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<DeclSpecifiers, ParseProcessError> {
|
|
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<Declarator, ParseProcessError> {
|
|
self.parse_direct_declarator()
|
|
}
|
|
|
|
fn parse_direct_declarator(&mut self) -> Result<Declarator, ParseProcessError> {
|
|
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<ArrayDimension, ParseProcessError> {
|
|
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<Vec<Param>, 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<Param, ParseProcessError> {
|
|
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<VarDeclStmt, ParseProcessError> {
|
|
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<VarDeclStmt, ParseProcessError> {
|
|
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<FuncDeclStmt, ParseProcessError> {
|
|
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<VarDeclStmt, ParseProcessError> {
|
|
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<Option<Expr>, 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<VarDeclStmtValue, ParseProcessError> {
|
|
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<Param, ParseProcessError> {
|
|
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<DeclaratorSuffix>,
|
|
) -> Result<Vec<ArrayDimension>, 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<DeclaratorSuffix>,
|
|
) -> Result<Vec<Param>, 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)
|
|
}
|
|
}
|
|
}
|
|
}
|