Parse function parameters
This commit is contained in:
parent
a605d182b4
commit
2184f7e654
@ -3,6 +3,7 @@
|
||||
## TODO
|
||||
|
||||
- Parse __more__ binary operators
|
||||
- Parse `Type name = value` bindings
|
||||
- Parse more complex bindings
|
||||
- Watch mode
|
||||
- Improve error messages
|
||||
@ -21,7 +22,7 @@
|
||||
|
||||
- [x] Parse function call parameters
|
||||
- [x] Codegen function call parameters
|
||||
- [ ] Parse function declaration arguments
|
||||
- [x] Parse function declaration arguments (Type id)
|
||||
- [ ] Begin work on semantic analysis
|
||||
- [ ] Symbol table
|
||||
- [ ] Typecheck bindings
|
||||
|
@ -29,6 +29,11 @@ pub struct Block {
|
||||
#[derive(Debug)]
|
||||
pub struct ParamsList {}
|
||||
|
||||
pub struct Parameter {
|
||||
pub identifier: Box<String>,
|
||||
pub datatype: Box<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expression {
|
||||
Number(Box<String>),
|
||||
|
@ -4,7 +4,10 @@ use crate::{
|
||||
syntax::utils::parse_token_type,
|
||||
};
|
||||
|
||||
use super::{ast::ParamsList, ParseResult};
|
||||
use super::{
|
||||
ast::{Parameter, ParamsList},
|
||||
utils, ParseResult,
|
||||
};
|
||||
|
||||
pub fn parse_params_list<'a>(
|
||||
tokens: &'a Vec<Token>,
|
||||
@ -21,6 +24,36 @@ pub fn parse_params_list<'a>(
|
||||
};
|
||||
current_pos = next_pos;
|
||||
|
||||
// Parse parameters definitions, separated by commas
|
||||
let mut parameters = Vec::<Parameter>::new();
|
||||
loop {
|
||||
let (next_parameter, next_pos) = match parse_param_definition(tokens, current_pos) {
|
||||
ParseResult::Ok(parameter, next_pos) => (parameter, next_pos),
|
||||
ParseResult::Err(error) => {
|
||||
return ParseResult::Err(error);
|
||||
}
|
||||
_ => break,
|
||||
};
|
||||
current_pos = next_pos;
|
||||
parameters.push(next_parameter);
|
||||
|
||||
// Parse comma. This also parses a trailing comma
|
||||
match parse_token_type(tokens, current_pos, TokenType::Comma) {
|
||||
ParseResult::Ok(_, next) => {
|
||||
current_pos = next;
|
||||
}
|
||||
// This should never happen
|
||||
ParseResult::Err(err) => return ParseResult::Err(err),
|
||||
ParseResult::Mismatch(_) => {
|
||||
// Something other than a comma was found. It must be a closing paren )
|
||||
// Still, break the loop, assume there are no more arguments
|
||||
// TODO: This could be a good place to write a detailed error?
|
||||
break;
|
||||
}
|
||||
ParseResult::Unmatched => break,
|
||||
};
|
||||
}
|
||||
|
||||
// Parse closing paren
|
||||
let (_closing_paren, next_pos) =
|
||||
match parse_token_type(tokens, current_pos, TokenType::RightParen) {
|
||||
@ -45,3 +78,60 @@ pub fn parse_params_list<'a>(
|
||||
|
||||
ParseResult::Ok(ParamsList {}, current_pos)
|
||||
}
|
||||
|
||||
fn parse_param_definition<'a>(
|
||||
tokens: &'a Vec<Token>,
|
||||
pos: usize,
|
||||
) -> ParseResult<Parameter, &Token> {
|
||||
// Parse a single parameter definition of the form:
|
||||
// - Type identifier
|
||||
// There will be more constructs in the future, like:
|
||||
// - Type identifier = default_value
|
||||
// - FunctionType identifier
|
||||
// - Pattern identifier (e.g. Some[String] value)?
|
||||
|
||||
let mut current_pos = pos;
|
||||
let (datatype, next_pos) =
|
||||
match utils::parse_token_type(tokens, current_pos, TokenType::Datatype) {
|
||||
ParseResult::Ok(token, next) => (token, next),
|
||||
ParseResult::Err(err) => {
|
||||
return ParseResult::Err(err);
|
||||
}
|
||||
// If there is no datatype this construction doesn't apply.
|
||||
// Return a mismatch and let the caller handle it
|
||||
ParseResult::Mismatch(t) => return ParseResult::Mismatch(t),
|
||||
ParseResult::Unmatched => return ParseResult::Unmatched,
|
||||
};
|
||||
current_pos = next_pos;
|
||||
|
||||
let (identifier, next_pos) =
|
||||
match utils::parse_token_type(tokens, current_pos, TokenType::Identifier) {
|
||||
ParseResult::Ok(token, next) => (token, next),
|
||||
ParseResult::Err(err) => {
|
||||
return ParseResult::Err(err);
|
||||
}
|
||||
// However, if we fail to parse an identifier, it's an error
|
||||
ParseResult::Mismatch(_) => {
|
||||
return ParseResult::Err(SyntaxError {
|
||||
reason: String::from("Expected an identifier for the parameter."),
|
||||
error_start: tokens[pos].position,
|
||||
error_end: tokens[pos].get_end_position(),
|
||||
});
|
||||
}
|
||||
ParseResult::Unmatched => {
|
||||
return ParseResult::Err(SyntaxError {
|
||||
reason: String::from("Expected an identifier for the parameter."),
|
||||
error_start: tokens[pos].position,
|
||||
error_end: tokens[pos].get_end_position(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
ParseResult::Ok(
|
||||
Parameter {
|
||||
identifier: Box::new(identifier.value.clone()),
|
||||
datatype: Box::new(datatype.value.clone()),
|
||||
},
|
||||
next_pos,
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user