Parser - Parse function declarations
This commit is contained in:
parent
9c7445d904
commit
250eddea71
1 changed files with 66 additions and 2 deletions
|
@ -115,6 +115,8 @@ impl Parser {
|
||||||
fn parse_statement(&mut self) -> ParserResult<ast::StmtNode> {
|
fn parse_statement(&mut self) -> ParserResult<ast::StmtNode> {
|
||||||
if self.expect(&[TokenType::Var]).is_some() {
|
if self.expect(&[TokenType::Var]).is_some() {
|
||||||
self.parse_var_declaration()
|
self.parse_var_declaration()
|
||||||
|
} else if self.expect(&[TokenType::Fun]).is_some() {
|
||||||
|
self.parse_fun_declaration("function")
|
||||||
} else if self.expect(&[TokenType::LeftBrace]).is_some() {
|
} else if self.expect(&[TokenType::LeftBrace]).is_some() {
|
||||||
self.parse_block()
|
self.parse_block()
|
||||||
} else if self.expect(&[TokenType::Address]).is_some() {
|
} else if self.expect(&[TokenType::Address]).is_some() {
|
||||||
|
@ -148,8 +150,8 @@ impl Parser {
|
||||||
|
|
||||||
/// Parse the following rule:
|
/// Parse the following rule:
|
||||||
/// ```
|
/// ```
|
||||||
/// declaration := "var" IDENTIFIER ";"
|
/// var_declaration := "var" IDENTIFIER ";"
|
||||||
/// declaration := "var" IDENTIFIER "=" expression ";"
|
/// var_declaration := "var" IDENTIFIER "=" expression ";"
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_var_declaration(&mut self) -> ParserResult<ast::StmtNode> {
|
fn parse_var_declaration(&mut self) -> ParserResult<ast::StmtNode> {
|
||||||
let name = match self.peek().token_type {
|
let name = match self.peek().token_type {
|
||||||
|
@ -167,6 +169,68 @@ impl Parser {
|
||||||
Ok(ast::StmtNode::VarDecl(name, initializer))
|
Ok(ast::StmtNode::VarDecl(name, initializer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse the following rule:
|
||||||
|
/// ```
|
||||||
|
/// fun_declaration := "fun" function
|
||||||
|
/// function := IDENTIFIER function_info
|
||||||
|
/// function_info := "(" parameters? ")" block
|
||||||
|
/// parameters := IDENTIFIER ( "," IDENTIFIER )*
|
||||||
|
/// ```
|
||||||
|
/// The `kind` parameter is used to generate error messages.
|
||||||
|
fn parse_fun_declaration(&mut self, kind: &'static str) -> ParserResult<ast::StmtNode> {
|
||||||
|
// Read the name
|
||||||
|
let name = match self.peek().token_type {
|
||||||
|
TokenType::Identifier(_) => self.advance().clone(),
|
||||||
|
_ => {
|
||||||
|
return Err(ParserError::new(
|
||||||
|
self.peek(),
|
||||||
|
&format!("expected {} name", kind),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read the list of parameter names
|
||||||
|
self.consume(
|
||||||
|
&TokenType::LeftParen,
|
||||||
|
&format!("expected '(' after {} name", kind),
|
||||||
|
)?;
|
||||||
|
let params = {
|
||||||
|
let mut params = Vec::new();
|
||||||
|
if !self.check(&TokenType::RightParen) {
|
||||||
|
loop {
|
||||||
|
if params.len() >= 255 {
|
||||||
|
return Err(ParserError::new(
|
||||||
|
self.peek(),
|
||||||
|
&format!("{} can't have more than 255 parameters", kind),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let TokenType::Identifier(_) = self.peek().token_type {
|
||||||
|
params.push(self.advance().clone());
|
||||||
|
} else {
|
||||||
|
return Err(ParserError::new(self.peek(), "parameter name expected"));
|
||||||
|
}
|
||||||
|
if self.expect(&[TokenType::Comma]).is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.consume(&TokenType::RightParen, "')' expected after parameters")?;
|
||||||
|
}
|
||||||
|
params
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read the function's body
|
||||||
|
self.consume(
|
||||||
|
&TokenType::LeftBrace,
|
||||||
|
&format!("'{{' expected before {} body", kind),
|
||||||
|
)?;
|
||||||
|
let block = self.parse_block()?;
|
||||||
|
Ok(ast::StmtNode::FunDecl {
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
body: block.extract_block_statements(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse the following rule:
|
/// Parse the following rule:
|
||||||
/// ```
|
/// ```
|
||||||
/// block := "{" statement* "}"
|
/// block := "{" statement* "}"
|
||||||
|
|
Loading…
Reference in a new issue