parsing struct definitions in ast
This commit is contained in:
parent
de22a9e01a
commit
a565c1e1e9
385
src/ast2/mod.rs
385
src/ast2/mod.rs
|
@ -620,8 +620,7 @@ pub mod intern {
|
||||||
fields,
|
fields,
|
||||||
} => {
|
} => {
|
||||||
let flags = StructFlags::new(packed, c_like, fields.len() as u32).pack();
|
let flags = StructFlags::new(packed, c_like, fields.len() as u32).pack();
|
||||||
let i = self.push_word(name.into_u32());
|
let i = self.extend_words([name.into_u32(), flags]);
|
||||||
let i = self.push_word(flags);
|
|
||||||
self.extend_words(
|
self.extend_words(
|
||||||
fields
|
fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1031,6 +1030,10 @@ enum ParseError {
|
||||||
#[error("Dummy Message.")]
|
#[error("Dummy Message.")]
|
||||||
UnmatchedParens(u32),
|
UnmatchedParens(u32),
|
||||||
#[error("Dummy Message.")]
|
#[error("Dummy Message.")]
|
||||||
|
ExpectedTypeDeclaration,
|
||||||
|
#[error("Dummy Message.")]
|
||||||
|
UnexpectedTypeAttributes,
|
||||||
|
#[error("Dummy Message.")]
|
||||||
UnmatchedSquareBracket(u32),
|
UnmatchedSquareBracket(u32),
|
||||||
#[error("Dummy Message.")]
|
#[error("Dummy Message.")]
|
||||||
ExpectedEndOfBlock,
|
ExpectedEndOfBlock,
|
||||||
|
@ -1697,10 +1700,6 @@ impl Ast {
|
||||||
(i, self.extra.len() as u32)
|
(i, self.extra.len() as u32)
|
||||||
}
|
}
|
||||||
fn set_tag_data_source_loc(&mut self, index: Index, tag: Tag, data: Data, loc: SourceLocation) {
|
fn set_tag_data_source_loc(&mut self, index: Index, tag: Tag, data: Data, loc: SourceLocation) {
|
||||||
eprintln!(
|
|
||||||
"{index} <- ({tag:?}, {:?}, {loc})",
|
|
||||||
ExpandedData::from((tag, data))
|
|
||||||
);
|
|
||||||
self.tags[index.index()] = tag;
|
self.tags[index.index()] = tag;
|
||||||
self.datas[index.index()] = data;
|
self.datas[index.index()] = data;
|
||||||
self.source_locs[index.index()] = loc;
|
self.source_locs[index.index()] = loc;
|
||||||
|
@ -1995,13 +1994,11 @@ pub mod ast_gen {
|
||||||
loc: tokens.current_source_location(),
|
loc: tokens.current_source_location(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
eprintln!("pointer qualifiers: {:?}", tokens.peek_token());
|
|
||||||
let &[cnst, vol, noalias] =
|
let &[cnst, vol, noalias] =
|
||||||
&tokens.eat_all_zero_or_once(&[Token::Const, Token::Volatile, Token::Noalias])[..3]
|
&tokens.eat_all_zero_or_once(&[Token::Const, Token::Volatile, Token::Noalias])[..3]
|
||||||
else {
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
eprintln!("pointee: {:?}", tokens.peek_token());
|
|
||||||
let pointee = self.parse_type(tokens)?;
|
let pointee = self.parse_type(tokens)?;
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
|
@ -2289,7 +2286,6 @@ pub mod ast_gen {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
eprintln!("semi: {:?}", tokens.peek_token());
|
|
||||||
let Some(_) = tokens.eat_token(Token::Semi) else {
|
let Some(_) = tokens.eat_token(Token::Semi) else {
|
||||||
break 'blk ErrorInfo {
|
break 'blk ErrorInfo {
|
||||||
error: ParseError::ExpectedToken(Token::Semi),
|
error: ParseError::ExpectedToken(Token::Semi),
|
||||||
|
@ -2477,6 +2473,9 @@ pub mod ast_gen {
|
||||||
loc: tokens.current_source_location(),
|
loc: tokens.current_source_location(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
if let Some(decl) = self.parse_constant_decls(tokens)? {
|
||||||
|
statements.push(decl);
|
||||||
|
} else {
|
||||||
match next.token() {
|
match next.token() {
|
||||||
Token::CloseBrace => {
|
Token::CloseBrace => {
|
||||||
break None;
|
break None;
|
||||||
|
@ -2487,59 +2486,30 @@ pub mod ast_gen {
|
||||||
Token::Var | Token::Let => {
|
Token::Var | Token::Let => {
|
||||||
statements.push(self.parse_var_decl(tokens)?);
|
statements.push(self.parse_var_decl(tokens)?);
|
||||||
}
|
}
|
||||||
Token::Const => {
|
|
||||||
statements.push(self.parse_const_decl(tokens)?);
|
|
||||||
}
|
|
||||||
Token::Fn => {
|
|
||||||
statements.push(self.parse_fn_decl(tokens));
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if self.is_statement(tokens) {
|
if self.is_statement(tokens) {
|
||||||
// expr -> statements
|
// expr -> statements
|
||||||
let expr = match self.parse_expr(tokens) {
|
let expr = self
|
||||||
Ok(i) => {
|
.parse_with_trailing_semi(tokens, |this, tokens| {
|
||||||
_ = tokens.eat_token(Token::Semi).ok_or(ErrorInfo {
|
this.parse_expr(tokens)
|
||||||
error: ParseError::ExpectedToken(Token::Semi),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
i
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_semi().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::ExpectedToken(Token::Semi),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
statements.push(expr);
|
statements.push(expr);
|
||||||
} else {
|
} else {
|
||||||
// expr -> trailing
|
// expr -> trailing
|
||||||
let expr = match self.parse_expr(tokens) {
|
let expr = self.parse_expr(tokens)?;
|
||||||
Ok(i) => {
|
|
||||||
if !tokens.is_next_token(Token::CloseBrace) {
|
if !tokens.is_next_token(Token::CloseBrace) {
|
||||||
return Err(ErrorInfo {
|
statements.push(self.push_error(
|
||||||
error: ParseError::ExpectedEndOfBlock,
|
ParseError::ExpectedEndOfBlock,
|
||||||
loc: tokens.current_source_location(),
|
tokens.current_source_location(),
|
||||||
});
|
));
|
||||||
}
|
} else {
|
||||||
|
|
||||||
i
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_braced().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::ExpectedToken(Token::CloseBrace),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
break Some(expr);
|
break Some(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.ast.set_block(block, statements, trailing, loc);
|
self.ast.set_block(block, statements, trailing, loc);
|
||||||
|
@ -2549,38 +2519,15 @@ pub mod ast_gen {
|
||||||
/// BLOCK <-
|
/// BLOCK <-
|
||||||
/// { STATEMENT* EXPRESSION? }
|
/// { STATEMENT* EXPRESSION? }
|
||||||
fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
fn parse_block(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
||||||
let loc = tokens.current_source_location();
|
let block = self.parse_braced(tokens, |this, tokens| {
|
||||||
|
let block = this.ast.reserve_node();
|
||||||
|
this.push_scope(block, intern::Index::invalid());
|
||||||
|
let block_result = this.parse_block_inner(block, tokens);
|
||||||
|
this.pop_scope();
|
||||||
|
|
||||||
let open_brace = tokens.eat_token(Token::OpenBrace).ok_or(ErrorInfo {
|
block_result
|
||||||
error: ParseError::ExpectedToken(Token::OpenBrace),
|
|
||||||
loc,
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let block = self.ast.reserve_node();
|
|
||||||
self.push_scope(block, intern::Index::invalid());
|
|
||||||
let block_result = self.parse_block_inner(block, tokens);
|
|
||||||
self.pop_scope();
|
|
||||||
|
|
||||||
let block = match block_result {
|
|
||||||
Ok(i) => {
|
|
||||||
let Some(_) = tokens.eat_token(Token::CloseBrace) else {
|
|
||||||
return Err(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedBrace(open_brace.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
i
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_braced().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedBrace(open_brace.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2611,16 +2558,13 @@ pub mod ast_gen {
|
||||||
/// IDENT : TYPENAME
|
/// IDENT : TYPENAME
|
||||||
fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
||||||
let loc = tokens.current_source_location();
|
let loc = tokens.current_source_location();
|
||||||
eprintln!("param name: {:?}", tokens.peek_token());
|
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
eprintln!("colon: {:?}", tokens.peek_token());
|
|
||||||
let Some(_) = tokens.eat_token(Token::Colon) else {
|
let Some(_) = tokens.eat_token(Token::Colon) else {
|
||||||
return Err(ErrorInfo {
|
return Err(ErrorInfo {
|
||||||
error: ParseError::ExpectedToken(Token::Colon),
|
error: ParseError::ExpectedToken(Token::Colon),
|
||||||
loc,
|
loc,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
eprintln!("param type: {:?}", tokens.peek_token());
|
|
||||||
let ty = self.parse_type(tokens)?;
|
let ty = self.parse_type(tokens)?;
|
||||||
|
|
||||||
let param = self.ast.push_parameter(name, ty, loc);
|
let param = self.ast.push_parameter(name, ty, loc);
|
||||||
|
@ -2710,27 +2654,8 @@ pub mod ast_gen {
|
||||||
}
|
}
|
||||||
|
|
||||||
Token::OpenParens => {
|
Token::OpenParens => {
|
||||||
_ = tokens.next();
|
let expr =
|
||||||
|
self.parse_parenthesised(tokens, |this, tokens| this.parse_expr(tokens))?;
|
||||||
let expr = match self.parse_expr(tokens) {
|
|
||||||
Ok(i) => {
|
|
||||||
let Some(_) = tokens.eat_token(Token::CloseParens) else {
|
|
||||||
return Err(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(next.token_pos().start),
|
|
||||||
loc,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
i
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_parens().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(next.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(expr);
|
return Ok(expr);
|
||||||
}
|
}
|
||||||
|
@ -2769,51 +2694,19 @@ pub mod ast_gen {
|
||||||
let loc = next.source_location();
|
let loc = next.source_location();
|
||||||
match next.token() {
|
match next.token() {
|
||||||
Token::OpenParens => {
|
Token::OpenParens => {
|
||||||
let rhs = if tokens.is_next_token(Token::CloseParens) {
|
let arguments = self.parse_parenthesised(tokens, |this, tokens| {
|
||||||
self.ast.push_argument_list([], loc)
|
if tokens.is_next_token(Token::CloseParens) {
|
||||||
|
Ok(this.ast.push_argument_list([], loc))
|
||||||
} else {
|
} else {
|
||||||
match self.parse_argument_list(tokens) {
|
this.parse_argument_list(tokens)
|
||||||
Ok(i) => {
|
|
||||||
_ = tokens.eat_token(Token::Comma);
|
|
||||||
|
|
||||||
let Some(_) = tokens.eat_token(Token::CloseParens) else {
|
|
||||||
let loc = tokens.current_source_location();
|
|
||||||
return Err(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(
|
|
||||||
next.token_pos().start,
|
|
||||||
),
|
|
||||||
loc,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
i
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_parens().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(next.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.push_error(err.error, err.loc)
|
return Ok(self.ast.push_call_expr(lhs, arguments, loc));
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(self.ast.push_call_expr(lhs, rhs, loc));
|
|
||||||
}
|
}
|
||||||
Token::OpenSquareBracket => {
|
Token::OpenSquareBracket => {
|
||||||
let subscript = match self.parse_expr(tokens) {
|
let subscript =
|
||||||
Ok(i) => i,
|
self.parse_bracketed(tokens, |this, tokens| this.parse_expr(tokens))?;
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_bracketed().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedSquareBracket(
|
|
||||||
next.token_pos().start,
|
|
||||||
),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(self
|
return Ok(self
|
||||||
.ast
|
.ast
|
||||||
|
@ -2919,7 +2812,6 @@ pub mod ast_gen {
|
||||||
let Some(tok) = tokens.peek_token() else {
|
let Some(tok) = tokens.peek_token() else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
eprintln!("maybe binop: {tok:?}");
|
|
||||||
let loc = tok.source_location();
|
let loc = tok.source_location();
|
||||||
let Some(prec) = PRECEDENCE_MAP.get(&tok.token()).cloned() else {
|
let Some(prec) = PRECEDENCE_MAP.get(&tok.token()).cloned() else {
|
||||||
break;
|
break;
|
||||||
|
@ -2931,7 +2823,6 @@ pub mod ast_gen {
|
||||||
|
|
||||||
// SAFETY: we peeked `tok`
|
// SAFETY: we peeked `tok`
|
||||||
let tok = tokens.next().unwrap();
|
let tok = tokens.next().unwrap();
|
||||||
eprintln!("binop: {tok:?}");
|
|
||||||
|
|
||||||
let lhs = node;
|
let lhs = node;
|
||||||
let rhs = self.parse_binary_expr(tokens, prec + 1)?;
|
let rhs = self.parse_binary_expr(tokens, prec + 1)?;
|
||||||
|
@ -3029,30 +2920,7 @@ pub mod ast_gen {
|
||||||
let iff = tokens.eat_token(Token::If).unwrap();
|
let iff = tokens.eat_token(Token::If).unwrap();
|
||||||
let loc = iff.source_location();
|
let loc = iff.source_location();
|
||||||
|
|
||||||
let open_parens = tokens.eat_token(Token::OpenParens).ok_or(ErrorInfo {
|
let cond = self.parse_parenthesised(tokens, |this, tokens| this.parse_expr(tokens))?;
|
||||||
error: ParseError::ExpectedToken(Token::OpenParens),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let cond = match self.parse_expr(tokens) {
|
|
||||||
Ok(i) => {
|
|
||||||
let Some(_) = tokens.eat_token(Token::CloseParens) else {
|
|
||||||
return Err(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(open_parens.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
i
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_parens().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::UnmatchedParens(open_parens.token_pos().start),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
self.push_error(err.error, err.loc)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let body = self.parse_expr_or_block_as_block(tokens)?;
|
let body = self.parse_expr_or_block_as_block(tokens)?;
|
||||||
|
|
||||||
|
@ -3100,6 +2968,73 @@ pub mod ast_gen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TYPE_DECL <-
|
||||||
|
/// type IDENTIFIER = TYPE_UNION ;
|
||||||
|
/// type IDENTIFIER = '(' (TYPE,)* ')' ;
|
||||||
|
/// type IDENTIFIER = extern? union { (IDENTIFIER: TYPE,)* }
|
||||||
|
/// type IDENTIFIER = extern? packed? enum { (IDENTIFIER (= EXPRESSION),)* }
|
||||||
|
/// type IDENTIFIER = extern? packed? struct { (IDENTIFIER: TYPE,)* }
|
||||||
|
fn parse_type_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
||||||
|
_ = tokens.eat_token(Token::Type).ok_or(ErrorInfo {
|
||||||
|
error: ParseError::ExpectedToken(Token::Type),
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let name = self.parse_ident(tokens)?;
|
||||||
|
let loc = tokens.current_source_location();
|
||||||
|
|
||||||
|
_ = tokens.eat_token(Token::Equal).ok_or(ErrorInfo {
|
||||||
|
error: ParseError::ExpectedToken(Token::Equal),
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let (has_attributes, c_like, packed) = {
|
||||||
|
let vec = tokens.eat_all_zero_or_once(&[Token::Extern, Token::Packed]);
|
||||||
|
(vec[0] || vec[1], vec[0], vec[1])
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(next) = tokens.peek_token() else {
|
||||||
|
return Err(ErrorInfo {
|
||||||
|
error: ParseError::ExpectedTypeDeclaration,
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
match next.token() {
|
||||||
|
Token::Struct => self.parse_struct_decl(tokens, name, c_like, packed, loc),
|
||||||
|
Token::Union => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
Token::Enum => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if has_attributes {
|
||||||
|
return Err(ErrorInfo {
|
||||||
|
error: ParseError::UnexpectedTypeAttributes,
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
match next.token() {
|
||||||
|
Token::OpenParens => {
|
||||||
|
// tuple
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
Token::Ident => {
|
||||||
|
// sumtype
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(ErrorInfo {
|
||||||
|
error: ParseError::ExpectedTypeDeclaration,
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// SUMTYPE_DECL <-
|
/// SUMTYPE_DECL <-
|
||||||
/// type IDENTIFIER = TYPE_UNION
|
/// type IDENTIFIER = TYPE_UNION
|
||||||
/// TYPE_UNION <-
|
/// TYPE_UNION <-
|
||||||
|
@ -3129,48 +3064,30 @@ pub mod ast_gen {
|
||||||
|
|
||||||
/// STRUCT_DECL <-
|
/// STRUCT_DECL <-
|
||||||
/// type IDENTIFIER = extern? packed? struct { STRUCT_FIELD,* }
|
/// type IDENTIFIER = extern? packed? struct { STRUCT_FIELD,* }
|
||||||
fn parse_struct_decl(&mut self, tokens: &mut TokenIterator) -> ParseResult<Index> {
|
fn parse_struct_decl(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
name: intern::Index,
|
||||||
|
c_like: bool,
|
||||||
|
packed: bool,
|
||||||
|
loc: SourceLocation,
|
||||||
|
) -> ParseResult<Index> {
|
||||||
// SAFETY: function invariance
|
// SAFETY: function invariance
|
||||||
let start = tokens.eat_token(Token::Type).unwrap();
|
|
||||||
let loc = start.source_location();
|
|
||||||
let name = self.parse_ident(tokens)?;
|
|
||||||
|
|
||||||
_ = tokens.eat_token(Token::Equal).ok_or(ErrorInfo {
|
|
||||||
error: ParseError::ExpectedToken(Token::Equal),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let flags = tokens.eat_all_zero_or_once(&[Token::Packed, Token::Extern]);
|
|
||||||
let (packed, c_like) = (flags[0], flags[1]);
|
|
||||||
|
|
||||||
_ = tokens.eat_token(Token::Struct).ok_or(ErrorInfo {
|
_ = tokens.eat_token(Token::Struct).ok_or(ErrorInfo {
|
||||||
error: ParseError::ExpectedToken(Token::Struct),
|
error: ParseError::ExpectedToken(Token::Struct),
|
||||||
loc: tokens.current_source_location(),
|
loc: tokens.current_source_location(),
|
||||||
})?;
|
})?;
|
||||||
_ = tokens.eat_token(Token::OpenBrace).ok_or(ErrorInfo {
|
|
||||||
error: ParseError::ExpectedToken(Token::OpenBrace),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
match self.parse_struct_fields(tokens) {
|
let decl = self.parse_braced(tokens, |this, tokens| {
|
||||||
Ok(fields) => {
|
this.parse_struct_fields(tokens).map(|fields| {
|
||||||
_ = tokens.eat_token(Token::Comma);
|
_ = tokens.eat_token(Token::Comma);
|
||||||
|
let struct_type = this.intern.get_struct_type(name, packed, c_like, fields);
|
||||||
|
this.ast.push_struct_decl(struct_type, loc)
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
_ = tokens.eat_token(Token::CloseBrace).ok_or(ErrorInfo {
|
Ok(decl)
|
||||||
error: ParseError::ExpectedToken(Token::CloseBrace),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
let struct_type = self.intern.get_struct_type(name, packed, c_like, fields);
|
|
||||||
return Ok(self.ast.push_struct_decl(struct_type, loc));
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tokens.advance_past_end_of_braced().ok_or(ErrorInfo {
|
|
||||||
error: ParseError::ExpectedToken(Token::CloseBrace),
|
|
||||||
loc: tokens.current_source_location(),
|
|
||||||
})?;
|
|
||||||
return Ok(self.push_error(err.error, err.loc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_with_trailing_semi<F>(
|
fn parse_with_trailing_semi<F>(
|
||||||
|
@ -3283,6 +3200,18 @@ pub mod ast_gen {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_bracketed<F>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<Index>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
|
||||||
|
{
|
||||||
|
self.parse_inner2(
|
||||||
|
tokens,
|
||||||
|
Token::OpenSquareBracket,
|
||||||
|
Token::CloseSquareBracket,
|
||||||
|
parse,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_braced<F>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<Index>
|
fn parse_braced<F>(&mut self, tokens: &mut TokenIterator, parse: F) -> ParseResult<Index>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
|
F: FnOnce(&mut Self, &mut TokenIterator) -> ParseResult<Index>,
|
||||||
|
@ -3329,11 +3258,38 @@ pub mod ast_gen {
|
||||||
tokens: &mut TokenIterator,
|
tokens: &mut TokenIterator,
|
||||||
) -> ParseResult<(intern::Index, intern::Index)> {
|
) -> ParseResult<(intern::Index, intern::Index)> {
|
||||||
let name = self.parse_ident(tokens)?;
|
let name = self.parse_ident(tokens)?;
|
||||||
|
let Some(_) = tokens.eat_token(Token::Colon) else {
|
||||||
|
return Err(ErrorInfo {
|
||||||
|
error: ParseError::ExpectedToken(Token::Colon),
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
});
|
||||||
|
};
|
||||||
let ty = self.parse_type(tokens)?;
|
let ty = self.parse_type(tokens)?;
|
||||||
|
|
||||||
return Ok((name, ty));
|
return Ok((name, ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CONSTANT_DECL <-
|
||||||
|
/// FUNCTION_DECL
|
||||||
|
/// GLOBAL_DECL
|
||||||
|
/// STRUCT_DECL
|
||||||
|
fn parse_constant_decls(
|
||||||
|
&mut self,
|
||||||
|
tokens: &mut TokenIterator,
|
||||||
|
) -> ParseResult<Option<Index>> {
|
||||||
|
let next = tokens.peek_token().ok_or(ErrorInfo {
|
||||||
|
error: ParseError::UnexpectedEndOfTokens,
|
||||||
|
loc: tokens.current_source_location(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match next.token() {
|
||||||
|
Token::Fn => Ok(Some(self.parse_fn_decl(tokens))),
|
||||||
|
Token::Const => self.parse_const_decl(tokens).map(|i| Some(i)),
|
||||||
|
Token::Type => self.parse_type_decl(tokens).map(|i| Some(i)),
|
||||||
|
_ => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// FILE <-
|
/// FILE <-
|
||||||
/// (FUNCTION_DECL | GLOBAL_DECL)*
|
/// (FUNCTION_DECL | GLOBAL_DECL)*
|
||||||
fn parse_file(&mut self, tokens: &mut TokenIterator) -> Index {
|
fn parse_file(&mut self, tokens: &mut TokenIterator) -> Index {
|
||||||
|
@ -3343,25 +3299,22 @@ pub mod ast_gen {
|
||||||
self.push_scope(file, intern::Index::invalid());
|
self.push_scope(file, intern::Index::invalid());
|
||||||
|
|
||||||
while let Some(next) = tokens.peek_token() {
|
while let Some(next) = tokens.peek_token() {
|
||||||
match next.token() {
|
let loc = next.source_location();
|
||||||
Token::Fn => {
|
let decl = match self.parse_constant_decls(tokens).and_then(|i| match i {
|
||||||
decls.push(self.parse_fn_decl(tokens));
|
Some(i) => Ok(i),
|
||||||
}
|
None => {
|
||||||
Token::Const => {
|
|
||||||
decls.push(match self.parse_const_decl(tokens) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(err) => self.push_error(err.error, err.loc),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// error node:
|
|
||||||
let error = ParseError::UnexpectedTokenAtFileScope;
|
let error = ParseError::UnexpectedTokenAtFileScope;
|
||||||
let node = self.push_error(error, next.source_location());
|
let node = self.push_error(error, loc);
|
||||||
decls.push(node);
|
|
||||||
|
|
||||||
self.find_next_fn_or_const(tokens);
|
self.find_next_fn_or_const(tokens);
|
||||||
|
|
||||||
|
Ok(node)
|
||||||
}
|
}
|
||||||
}
|
}) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(err) => self.push_error(err.error, err.loc),
|
||||||
|
};
|
||||||
|
decls.push(decl);
|
||||||
}
|
}
|
||||||
self.pop_scope();
|
self.pop_scope();
|
||||||
|
|
||||||
|
@ -3437,7 +3390,7 @@ pub mod ast_gen {
|
||||||
|
|
||||||
fn find_next_fn_or_const(&mut self, tokens: &mut TokenIterator) -> Option<()> {
|
fn find_next_fn_or_const(&mut self, tokens: &mut TokenIterator) -> Option<()> {
|
||||||
tokens
|
tokens
|
||||||
.advance_until_before_one_of(&[Token::Const, Token::Fn])
|
.advance_until_before_one_of(&[Token::Const, Token::Fn, Token::Type])
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,14 @@ use compiler::{
|
||||||
triples::{MirBuilder, IR},
|
triples::{MirBuilder, IR},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn ast_tree(tokens: &Tokenizer) -> Tree {
|
||||||
|
let mut tree = Tree::new();
|
||||||
|
tree.parse(tokens.iter()).unwrap();
|
||||||
|
tree.fold_comptime();
|
||||||
|
|
||||||
|
tree
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cmd = clap::Command::new("sea")
|
let cmd = clap::Command::new("sea")
|
||||||
.bin_name("sea")
|
.bin_name("sea")
|
||||||
|
@ -37,13 +45,10 @@ fn main() {
|
||||||
|
|
||||||
let tokens = Tokenizer::new(&source).unwrap();
|
let tokens = Tokenizer::new(&source).unwrap();
|
||||||
|
|
||||||
let mut tree = Tree::new();
|
|
||||||
tree.parse(tokens.iter()).unwrap();
|
|
||||||
tree.fold_comptime();
|
|
||||||
|
|
||||||
if let Some((cmd, _matches)) = matches.subcommand() {
|
if let Some((cmd, _matches)) = matches.subcommand() {
|
||||||
match cmd {
|
match cmd {
|
||||||
"ast" => {
|
"ast" => {
|
||||||
|
let mut tree = ast_tree(&tokens);
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
tree.render(&mut buf).unwrap();
|
tree.render(&mut buf).unwrap();
|
||||||
println!("AST:\n{buf}");
|
println!("AST:\n{buf}");
|
||||||
|
@ -55,6 +60,7 @@ fn main() {
|
||||||
println!("AST (new):\n{tree2}");
|
println!("AST (new):\n{tree2}");
|
||||||
}
|
}
|
||||||
"ir" => {
|
"ir" => {
|
||||||
|
let mut tree = ast_tree(&tokens);
|
||||||
let mut ir = IR::new();
|
let mut ir = IR::new();
|
||||||
let builder = ir.build(&mut tree);
|
let builder = ir.build(&mut tree);
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
@ -62,6 +68,7 @@ fn main() {
|
||||||
println!("IR:\n{buf}");
|
println!("IR:\n{buf}");
|
||||||
}
|
}
|
||||||
"mir" => {
|
"mir" => {
|
||||||
|
let mut tree = ast_tree(&tokens);
|
||||||
let mut ir = IR::new();
|
let mut ir = IR::new();
|
||||||
ir.build(&mut tree);
|
ir.build(&mut tree);
|
||||||
|
|
||||||
|
@ -77,6 +84,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"asm" => {
|
"asm" => {
|
||||||
|
let mut tree = ast_tree(&tokens);
|
||||||
let mut ir = IR::new();
|
let mut ir = IR::new();
|
||||||
ir.build(&mut tree);
|
ir.build(&mut tree);
|
||||||
|
|
||||||
|
|
8
tests/legal/struct.sea
Normal file
8
tests/legal/struct.sea
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
type MyStruct = struct {
|
||||||
|
i: i32,
|
||||||
|
b: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn square_if_true(arg: MyStruct) -> i32 {
|
||||||
|
0
|
||||||
|
}
|
Loading…
Reference in a new issue