Parse minimal function call
This commit is contained in:
parent
c4d13e76bc
commit
971b9d9516
@ -1,14 +1,11 @@
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionCall {
|
||||
pub identifier: Box<String>
|
||||
pub identifier: Box<String>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArgumentsList {
|
||||
pub arguments: Vec<Box<Argument>>
|
||||
pub arguments: Vec<Box<Argument>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
pub mod functions;
|
||||
|
||||
|
||||
pub struct ModuleAST {
|
||||
pub declarations: Vec<TopLevelDeclaration>,
|
||||
}
|
||||
|
92
src/syntax/functions/arguments_list.rs
Normal file
92
src/syntax/functions/arguments_list.rs
Normal file
@ -0,0 +1,92 @@
|
||||
use crate::{
|
||||
error_handling::SyntaxError,
|
||||
lexic::token::{Token, TokenType},
|
||||
syntax::{ast::functions::ArgumentsList, utils::parse_token_type, ParseResult},
|
||||
};
|
||||
|
||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<ArgumentsList, &Token> {
|
||||
let mut current_pos = pos;
|
||||
|
||||
let (opening_paren, next_pos) =
|
||||
match parse_token_type(tokens, current_pos, TokenType::LeftParen) {
|
||||
ParseResult::Ok(t, next) => (t, next),
|
||||
ParseResult::Err(err) => return ParseResult::Err(err),
|
||||
ParseResult::Mismatch(t) => return ParseResult::Mismatch(t),
|
||||
ParseResult::Unmatched => return ParseResult::Unmatched,
|
||||
};
|
||||
current_pos = next_pos;
|
||||
|
||||
// Parse closing paren
|
||||
let (_closing_paren, next_pos) =
|
||||
match parse_token_type(tokens, current_pos, TokenType::RightParen) {
|
||||
ParseResult::Ok(t, next) => (t, next),
|
||||
ParseResult::Err(err) => return ParseResult::Err(err),
|
||||
ParseResult::Mismatch(t) => {
|
||||
return ParseResult::Err(SyntaxError {
|
||||
reason: String::from("Expected a closing paren after the function identifier."),
|
||||
error_start: t.position,
|
||||
error_end: t.get_end_position(),
|
||||
});
|
||||
}
|
||||
ParseResult::Unmatched => {
|
||||
return ParseResult::Err(SyntaxError {
|
||||
reason: String::from("Expected a closing paren after the function identifier."),
|
||||
error_start: opening_paren.position,
|
||||
error_end: opening_paren.get_end_position(),
|
||||
});
|
||||
}
|
||||
};
|
||||
current_pos = next_pos;
|
||||
|
||||
ParseResult::Ok(
|
||||
ArgumentsList {
|
||||
arguments: Vec::new(),
|
||||
},
|
||||
current_pos,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::lexic::get_tokens;
|
||||
|
||||
#[test]
|
||||
fn should_parse_empty_list() {
|
||||
let tokens = get_tokens(&String::from("()")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(list, next) = fun_decl else {
|
||||
panic!("Expected an unmatched result: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 2);
|
||||
assert_eq!(list.arguments.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_empty_list_with_whitespace() {
|
||||
let tokens = get_tokens(&String::from("( ) ")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(list, next) = fun_decl else {
|
||||
panic!("Expected a result, got: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 2);
|
||||
assert_eq!(list.arguments.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_empty_list_with_whitespace_2() {
|
||||
let tokens = get_tokens(&String::from("(\n \n)")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(list, next) = fun_decl else {
|
||||
panic!("Expected a result, got: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 3);
|
||||
assert_eq!(list.arguments.len(), 0);
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
use crate::{lexic::token::{Token, TokenType}, syntax::{ParseResult, ast::functions::FunctionCall, utils::parse_token_type}, error_handling::SyntaxError};
|
||||
|
||||
|
||||
use crate::{
|
||||
error_handling::SyntaxError,
|
||||
lexic::token::{Token, TokenType},
|
||||
syntax::{ast::functions::FunctionCall, utils::parse_token_type, ParseResult},
|
||||
};
|
||||
|
||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<FunctionCall, ()> {
|
||||
let mut current_pos = pos;
|
||||
|
||||
// TODO: Use an expression instead of a fixed identifier
|
||||
// Parse identifier
|
||||
let (identifier, next_pos) = match parse_token_type(tokens, current_pos, TokenType::Identifier)
|
||||
{
|
||||
@ -20,15 +23,25 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Function
|
||||
current_pos = next_pos;
|
||||
|
||||
// Parse arguments list
|
||||
let (args_list, next_pos) = match super::arguments_list::try_parse(tokens, current_pos) {
|
||||
ParseResult::Ok(args, next) => (args, next),
|
||||
ParseResult::Err(err) => return ParseResult::Err(err),
|
||||
ParseResult::Mismatch(_) => {
|
||||
return ParseResult::Unmatched;
|
||||
}
|
||||
ParseResult::Unmatched => {
|
||||
return ParseResult::Unmatched;
|
||||
}
|
||||
};
|
||||
current_pos = next_pos;
|
||||
|
||||
ParseResult::Unmatched
|
||||
ParseResult::Ok(FunctionCall { identifier: Box::new(identifier.value.clone()) }, current_pos)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::lexic::get_tokens;
|
||||
use super::*;
|
||||
use crate::lexic::get_tokens;
|
||||
|
||||
#[test]
|
||||
fn should_not_parse_identifier_alone() {
|
||||
@ -39,4 +52,40 @@ mod tests {
|
||||
panic!("Expected an unmatched result: {:?}", fun_decl);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_minimal_construct() {
|
||||
let tokens = get_tokens(&String::from("function_name()")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(_call, next) = fun_decl else {
|
||||
panic!("Expected a result, got: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_minimal_construct_2() {
|
||||
let tokens = get_tokens(&String::from("function_name ( )")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(_call, next) = fun_decl else {
|
||||
panic!("Expected a result, got: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_minimal_construct_3() {
|
||||
let tokens = get_tokens(&String::from("function_name\n(\n \n)")).unwrap();
|
||||
let fun_decl = try_parse(&tokens, 0);
|
||||
|
||||
let ParseResult::Ok(_call, next) = fun_decl else {
|
||||
panic!("Expected a result, got: {:?}", fun_decl);
|
||||
};
|
||||
|
||||
assert_eq!(next, 5);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod function_call;
|
||||
pub mod arguments_list;
|
||||
pub mod function_call;
|
||||
|
@ -4,9 +4,9 @@ mod binding;
|
||||
mod block;
|
||||
mod expression;
|
||||
mod function_declaration;
|
||||
mod functions;
|
||||
mod params_list;
|
||||
mod utils;
|
||||
mod functions;
|
||||
|
||||
pub mod ast;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user