Parser - Some refactoring of code that handles identifiers
This commit is contained in:
parent
e006a12c80
commit
334dc99752
1 changed files with 21 additions and 29 deletions
|
@ -200,10 +200,7 @@ impl Parser {
|
||||||
/// var_declaration := "var" IDENTIFIER "=" expression ";"
|
/// var_declaration := "var" IDENTIFIER "=" expression ";"
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_var_declaration(&mut self) -> SloxResult<StmtNode> {
|
fn parse_var_declaration(&mut self) -> SloxResult<StmtNode> {
|
||||||
let name = match self.peek().token_type {
|
let name = self.consume_identifier("expected variable name")?;
|
||||||
TokenType::Identifier(_) => self.advance().clone(),
|
|
||||||
_ => return self.error("expected variable name"),
|
|
||||||
};
|
|
||||||
let initializer: Option<ExprNode> = match self.expect(&[TokenType::Equal]) {
|
let initializer: Option<ExprNode> = match self.expect(&[TokenType::Equal]) {
|
||||||
Some(_) => Some(self.parse_expression()?),
|
Some(_) => Some(self.parse_expression()?),
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -220,12 +217,7 @@ impl Parser {
|
||||||
/// class := IDENTIFIER "{" function* "}"
|
/// class := IDENTIFIER "{" function* "}"
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_class(&mut self) -> SloxResult<StmtNode> {
|
fn parse_class(&mut self) -> SloxResult<StmtNode> {
|
||||||
// Read the name
|
let name = self.consume_identifier("expected class name")?;
|
||||||
let name = match self.peek().token_type {
|
|
||||||
TokenType::Identifier(_) => self.advance().clone(),
|
|
||||||
_ => return self.error("class name expected"),
|
|
||||||
};
|
|
||||||
// Read the body
|
|
||||||
self.consume(&TokenType::LeftBrace, "'{' expected")?;
|
self.consume(&TokenType::LeftBrace, "'{' expected")?;
|
||||||
let mut methods = Vec::new();
|
let mut methods = Vec::new();
|
||||||
while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
|
while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
|
||||||
|
@ -245,11 +237,7 @@ impl Parser {
|
||||||
/// ```
|
/// ```
|
||||||
/// The `kind` parameter is used to generate error messages.
|
/// The `kind` parameter is used to generate error messages.
|
||||||
fn parse_function(&mut self, kind: FunctionKind) -> SloxResult<StmtNode> {
|
fn parse_function(&mut self, kind: FunctionKind) -> SloxResult<StmtNode> {
|
||||||
// Read the name
|
let name = self.consume_identifier(&format!("expected {} name", kind.name()))?;
|
||||||
let name = match self.peek().token_type {
|
|
||||||
TokenType::Identifier(_) => self.advance().clone(),
|
|
||||||
_ => return self.error_mv(format!("expected {} name", kind.name())),
|
|
||||||
};
|
|
||||||
let (params, block) = self.parse_function_info(kind)?;
|
let (params, block) = self.parse_function_info(kind)?;
|
||||||
Ok(StmtNode::FunDecl(FunDecl {
|
Ok(StmtNode::FunDecl(FunDecl {
|
||||||
name,
|
name,
|
||||||
|
@ -284,15 +272,12 @@ impl Parser {
|
||||||
kind.max_params()
|
kind.max_params()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let TokenType::Identifier(name) = &self.peek().token_type {
|
let name = self.consume_identifier("parameter name expected")?;
|
||||||
if names.contains(name) {
|
if names.contains(&name.lexeme) {
|
||||||
return self.error_mv(format!("duplicate {} parameter", kind.name()));
|
return self.error_mv(format!("duplicate {} parameter", kind.name()));
|
||||||
}
|
}
|
||||||
names.insert(name.to_owned());
|
names.insert(name.lexeme);
|
||||||
params.push(self.advance().clone());
|
params.push(self.advance().clone());
|
||||||
} else {
|
|
||||||
return self.error("parameter name expected");
|
|
||||||
}
|
|
||||||
if self.expect(&[TokenType::Comma]).is_none() {
|
if self.expect(&[TokenType::Comma]).is_none() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -357,11 +342,7 @@ impl Parser {
|
||||||
/// labelled_loop := "@" IDENTIFIER for_statement
|
/// labelled_loop := "@" IDENTIFIER for_statement
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_labelled_loop(&mut self) -> SloxResult<StmtNode> {
|
fn parse_labelled_loop(&mut self) -> SloxResult<StmtNode> {
|
||||||
let name_token = match self.peek().token_type {
|
let name_token = self.consume_identifier("identifier expected after '@'")?;
|
||||||
TokenType::Identifier(_) => self.advance().clone(),
|
|
||||||
_ => return self.error("identifier expected after '@'"),
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.expect(&[TokenType::While]).is_some() {
|
if self.expect(&[TokenType::While]).is_some() {
|
||||||
self.parse_while_statement(Some(name_token))
|
self.parse_while_statement(Some(name_token))
|
||||||
} else if self.expect(&[TokenType::For]).is_some() {
|
} else if self.expect(&[TokenType::For]).is_some() {
|
||||||
|
@ -478,7 +459,7 @@ impl Parser {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let loop_name = if let TokenType::Identifier(_) = self.peek().token_type {
|
let loop_name = if self.peek().is_identifier() {
|
||||||
let name_token = self.advance().clone();
|
let name_token = self.advance().clone();
|
||||||
if !self.find_named_loop(&name_token.lexeme) {
|
if !self.find_named_loop(&name_token.lexeme) {
|
||||||
self.expect(&[TokenType::Semicolon]);
|
self.expect(&[TokenType::Semicolon]);
|
||||||
|
@ -817,6 +798,17 @@ impl Parser {
|
||||||
self.previous()
|
self.previous()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advance if the current token is an identifier, returning a clone of
|
||||||
|
/// the token. If it isn't, an error with the specified message is
|
||||||
|
/// returned instead.
|
||||||
|
fn consume_identifier(&mut self, message: &str) -> SloxResult<Token> {
|
||||||
|
if self.peek().is_identifier() {
|
||||||
|
Ok(self.advance().clone())
|
||||||
|
} else {
|
||||||
|
self.error(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check whether the end of token stream has been reached by checking
|
/// Check whether the end of token stream has been reached by checking
|
||||||
/// for the `EOF` token.
|
/// for the `EOF` token.
|
||||||
fn is_at_end(&self) -> bool {
|
fn is_at_end(&self) -> bool {
|
||||||
|
|
Loading…
Reference in a new issue