Simplify ParseResult struct
This commit is contained in:
parent
d822c64fd7
commit
1348020cd7
@ -13,7 +13,10 @@ impl Transpilable for Binding<'_> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{lexic::token::{Token, TokenType}, syntax::ast::{var_binding::Binding, Expression}};
|
use crate::{
|
||||||
|
lexic::token::{Token, TokenType},
|
||||||
|
syntax::ast::{var_binding::Binding, Expression},
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn binding_should_transpile() {
|
fn binding_should_transpile() {
|
||||||
|
@ -34,6 +34,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!("function id() {\n\n}", transpiled);
|
assert_eq!("function id() {\n\n}", transpiled);
|
||||||
}
|
}
|
||||||
|
_ => panic!("Not implemented: Expression at top level"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,10 @@ impl Transpilable for ModuleAST<'_> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{lexic::token::{Token, TokenType}, syntax::ast::{var_binding::Binding, Expression, TopLevelDeclaration}};
|
use crate::{
|
||||||
|
lexic::token::{Token, TokenType},
|
||||||
|
syntax::ast::{var_binding::Binding, Expression, TopLevelDeclaration},
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn module_ast_should_transpile() {
|
fn module_ast_should_transpile() {
|
||||||
|
@ -7,6 +7,7 @@ impl Transpilable for TopLevelDeclaration<'_> {
|
|||||||
match self {
|
match self {
|
||||||
TopLevelDeclaration::Binding(binding) => binding.transpile(),
|
TopLevelDeclaration::Binding(binding) => binding.transpile(),
|
||||||
TopLevelDeclaration::FunctionDeclaration(fun) => fun.transpile(),
|
TopLevelDeclaration::FunctionDeclaration(fun) => fun.transpile(),
|
||||||
|
_ => panic!("Not implemented: Expression at top level"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ pub enum TokenType {
|
|||||||
FUN,
|
FUN,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
pub token_type: TokenType,
|
pub token_type: TokenType,
|
||||||
// The token as a raw string
|
// The token as a raw string
|
||||||
|
@ -51,12 +51,15 @@ impl SemanticCheck for TopLevelDeclaration<'_> {
|
|||||||
binding_name
|
binding_name
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Err(MistiError::Semantic(error));
|
return Err(MistiError::Semantic(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.insert(binding_name.clone(), SymbolEntry::new_variable(datatype.value.clone()));
|
scope.insert(
|
||||||
|
binding_name.clone(),
|
||||||
|
SymbolEntry::new_variable(datatype.value.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -77,10 +80,14 @@ impl SemanticCheck for TopLevelDeclaration<'_> {
|
|||||||
return Err(MistiError::Semantic(error));
|
return Err(MistiError::Semantic(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.insert(function_name, SymbolEntry::new_function(vec![], "Unit".into()));
|
scope.insert(
|
||||||
|
function_name,
|
||||||
|
SymbolEntry::new_function(vec![], "Unit".into()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
_ => panic!("Not implemented"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ pub struct ModuleAST<'a> {
|
|||||||
pub enum TopLevelDeclaration<'a> {
|
pub enum TopLevelDeclaration<'a> {
|
||||||
Binding(var_binding::Binding<'a>),
|
Binding(var_binding::Binding<'a>),
|
||||||
FunctionDeclaration(FunctionDeclaration<'a>),
|
FunctionDeclaration(FunctionDeclaration<'a>),
|
||||||
|
Expression(Expression<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -5,7 +5,7 @@ use crate::error_handling::SyntaxError;
|
|||||||
use crate::lexic::token::{Token, TokenType};
|
use crate::lexic::token::{Token, TokenType};
|
||||||
use crate::utils::Result3;
|
use crate::utils::Result3;
|
||||||
|
|
||||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Binding, ()> {
|
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Binding> {
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
// TODO: Detect if the binding starts with a datatype
|
// TODO: Detect if the binding starts with a datatype
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
use super::{ast::Block, utils::parse_token_type, ParseResult};
|
use super::{ast::Block, utils::parse_token_type, ParseResult};
|
||||||
|
|
||||||
// Assumes that the token at `pos` is a {
|
// Assumes that the token at `pos` is a {
|
||||||
pub fn parse_block<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Block, &Token> {
|
pub fn parse_block<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Block> {
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
let (opening_brace, next_pos) =
|
let (opening_brace, next_pos) =
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
/// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let (term, next_pos) = match super::term::try_parse(tokens, pos) {
|
let (term, next_pos) = match super::term::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
||||||
_ => return ParseResult::Unmatched,
|
_ => return ParseResult::Unmatched,
|
||||||
@ -21,7 +21,7 @@ fn parse_many<'a>(
|
|||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
) -> ParseResult<Expression<'a>, ()> {
|
) -> ParseResult<Expression<'a>> {
|
||||||
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
||||||
|
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// equality = comparison, (("==" | "!="), comparison )*;
|
/// equality = comparison, (("==" | "!="), comparison )*;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let (comparison, next_pos) = match super::comparison::try_parse(tokens, pos) {
|
let (comparison, next_pos) = match super::comparison::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
||||||
_ => return ParseResult::Unmatched,
|
_ => return ParseResult::Unmatched,
|
||||||
@ -21,7 +21,7 @@ fn parse_many<'a>(
|
|||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
) -> ParseResult<Expression<'a>, ()> {
|
) -> ParseResult<Expression<'a>> {
|
||||||
// equality = comparison, (("==" | "!="), comparison )*;
|
// equality = comparison, (("==" | "!="), comparison )*;
|
||||||
|
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// factor = unary, (("/" | "*"), unary)*;
|
/// factor = unary, (("/" | "*"), unary)*;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let (unary, next_pos) = match super::unary::try_parse(tokens, pos) {
|
let (unary, next_pos) = match super::unary::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
||||||
_ => return ParseResult::Unmatched,
|
_ => return ParseResult::Unmatched,
|
||||||
@ -21,7 +21,7 @@ fn parse_many<'a>(
|
|||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
) -> ParseResult<Expression<'a>, ()> {
|
) -> ParseResult<Expression<'a>> {
|
||||||
// (("/" | "*"), unary)*
|
// (("/" | "*"), unary)*
|
||||||
|
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
/// function call expr = primary, "(", (arguments list)?, ")"
|
/// function call expr = primary, "(", (arguments list)?, ")"
|
||||||
/// | primary;
|
/// | primary;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let (primary_expr, next_pos) = match super::primary::try_parse(tokens, pos) {
|
let (primary_expr, next_pos) = match super::primary::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
||||||
_ => return ParseResult::Unmatched,
|
_ => return ParseResult::Unmatched,
|
||||||
|
@ -10,7 +10,7 @@ mod term;
|
|||||||
mod unary;
|
mod unary;
|
||||||
|
|
||||||
/// Expression is defined in the grammar.
|
/// Expression is defined in the grammar.
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
return equality::try_parse(tokens, pos);
|
return equality::try_parse(tokens, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// primary = number | string | boolean | identifier | ("(", expression, ")");
|
/// primary = number | string | boolean | identifier | ("(", expression, ")");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
match tokens.get_significant(pos) {
|
match tokens.get_significant(pos) {
|
||||||
Some((token, token_pos)) => match token.token_type {
|
Some((token, token_pos)) => match token.token_type {
|
||||||
TokenType::Number => ParseResult::Ok(Expression::Number(&token.value), token_pos + 1),
|
TokenType::Number => ParseResult::Ok(Expression::Number(&token.value), token_pos + 1),
|
||||||
@ -27,7 +27,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_parenthesized_expression(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
fn parse_parenthesized_expression(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let expression = super::try_parse(tokens, pos + 1);
|
let expression = super::try_parse(tokens, pos + 1);
|
||||||
match expression {
|
match expression {
|
||||||
ParseResult::Ok(expression, next_pos) => match tokens.get(next_pos) {
|
ParseResult::Ok(expression, next_pos) => match tokens.get(next_pos) {
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// term = factor, (("-" | "+"), factor)*;
|
/// term = factor, (("-" | "+"), factor)*;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
let (factor, next_pos) = match super::factor::try_parse(tokens, pos) {
|
let (factor, next_pos) = match super::factor::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
ParseResult::Ok(expr, next_pos) => (expr, next_pos),
|
||||||
_ => return ParseResult::Unmatched,
|
_ => return ParseResult::Unmatched,
|
||||||
@ -21,7 +21,7 @@ fn parse_many<'a>(
|
|||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
) -> ParseResult<Expression<'a>, ()> {
|
) -> ParseResult<Expression<'a>> {
|
||||||
// term = factor, (("-" | "+"), factor)*;
|
// term = factor, (("-" | "+"), factor)*;
|
||||||
|
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
|
@ -11,7 +11,7 @@ use super::function_call_expr;
|
|||||||
/// unary = ("!" | "-"), expression
|
/// unary = ("!" | "-"), expression
|
||||||
/// | function call expr;
|
/// | function call expr;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression, ()> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParseResult<Expression> {
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
Some(token) if token.value == "!" || token.value == "-" => {
|
Some(token) if token.value == "!" || token.value == "-" => {
|
||||||
match super::try_parse(tokens, pos + 1) {
|
match super::try_parse(tokens, pos + 1) {
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<ArgumentsList, &Token> {
|
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<ArgumentsList> {
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
let (opening_paren, next_pos) =
|
let (opening_paren, next_pos) =
|
||||||
|
@ -14,7 +14,7 @@ use super::{
|
|||||||
params_list::parse_params_list,
|
params_list::parse_params_list,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<FunctionDeclaration, ()> {
|
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<FunctionDeclaration> {
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
// `fun` keyword
|
// `fun` keyword
|
||||||
|
@ -9,10 +9,7 @@ use super::super::{
|
|||||||
utils, ParseResult,
|
utils, ParseResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse_params_list<'a>(
|
pub fn parse_params_list<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<ParamsList> {
|
||||||
tokens: &'a Vec<Token>,
|
|
||||||
pos: usize,
|
|
||||||
) -> ParseResult<ParamsList, &Token> {
|
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
let (opening_paren, next_pos) =
|
let (opening_paren, next_pos) =
|
||||||
@ -24,6 +21,14 @@ pub fn parse_params_list<'a>(
|
|||||||
};
|
};
|
||||||
current_pos = next_pos;
|
current_pos = next_pos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
val (opening_paren, next_pos) = try parse_token_type(...)
|
||||||
|
|
||||||
|
val (next_parameter, next_pos) = try parse_param_definition(...) catch
|
||||||
|
case ::Err(e) { return ::Err(e) }
|
||||||
|
else { break }
|
||||||
|
*/
|
||||||
|
|
||||||
// Parse parameters definitions, separated by commas
|
// Parse parameters definitions, separated by commas
|
||||||
let mut parameters = Vec::<Parameter>::new();
|
let mut parameters = Vec::<Parameter>::new();
|
||||||
loop {
|
loop {
|
||||||
@ -79,10 +84,7 @@ pub fn parse_params_list<'a>(
|
|||||||
ParseResult::Ok(ParamsList {}, current_pos)
|
ParseResult::Ok(ParamsList {}, current_pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_param_definition<'a>(
|
fn parse_param_definition<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Parameter> {
|
||||||
tokens: &'a Vec<Token>,
|
|
||||||
pos: usize,
|
|
||||||
) -> ParseResult<Parameter, &Token> {
|
|
||||||
// Parse a single parameter definition of the form:
|
// Parse a single parameter definition of the form:
|
||||||
// - Type identifier
|
// - Type identifier
|
||||||
// There will be more constructs in the future, like:
|
// There will be more constructs in the future, like:
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
# Grammar
|
# Grammar
|
||||||
|
|
||||||
|
|
||||||
## Module
|
## Source file
|
||||||
|
|
||||||
A module is (commonly) a single source file.
|
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
module = top level declaration*
|
source file = top level statement*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Top level declaration
|
## Top level statement
|
||||||
|
|
||||||
|
Current focus: Have a mvp compiler (w lexical/syntactic/semantic analysis + codegen) for
|
||||||
|
simple function calls, and then implement other features top down
|
||||||
|
|
||||||
```ebnf
|
```ebnf
|
||||||
top level declaration = function declaration
|
top level statement = expression
|
||||||
|
| function declaration
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ use ast::ModuleAST;
|
|||||||
use self::ast::TopLevelDeclaration;
|
use self::ast::TopLevelDeclaration;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseResult<A, B> {
|
pub enum ParseResult<A> {
|
||||||
/// The parsing was a success. The first element is the parsed construct,
|
/// The parsing was a success. The first element is the parsed construct,
|
||||||
/// the second element is the position of the next token to parse
|
/// the second element is the position of the next token to parse
|
||||||
Ok(A, usize),
|
Ok(A, usize),
|
||||||
@ -26,11 +26,19 @@ pub enum ParseResult<A, B> {
|
|||||||
Err(SyntaxError),
|
Err(SyntaxError),
|
||||||
/// Some special value was expected, but something else was found.
|
/// Some special value was expected, but something else was found.
|
||||||
/// The inside element is the something else found.
|
/// The inside element is the something else found.
|
||||||
Mismatch(B),
|
Mismatch(Token),
|
||||||
/// This parsing didn't succeed, but it's not a fatal error.
|
/// This parsing didn't succeed, but it's not a fatal error.
|
||||||
Unmatched,
|
Unmatched,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ParsingError {
|
||||||
|
Mismatch(Token),
|
||||||
|
Unmatch,
|
||||||
|
Error(SyntaxError),
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParsingResult<A> = Result<(A, usize), ParsingError>;
|
||||||
|
|
||||||
/// Constructs the Misti AST from a vector of tokens
|
/// Constructs the Misti AST from a vector of tokens
|
||||||
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
|
||||||
let mut top_level_declarations = Vec::new();
|
let mut top_level_declarations = Vec::new();
|
||||||
@ -70,7 +78,7 @@ pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError
|
|||||||
fn next_construct<'a>(
|
fn next_construct<'a>(
|
||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
current_pos: usize,
|
current_pos: usize,
|
||||||
) -> ParseResult<TopLevelDeclaration, ()> {
|
) -> ParseResult<TopLevelDeclaration> {
|
||||||
None.or_else(
|
None.or_else(
|
||||||
|| match functions::function_declaration::try_parse(tokens, current_pos) {
|
|| match functions::function_declaration::try_parse(tokens, current_pos) {
|
||||||
ParseResult::Ok(declaration, next_pos) => Some(ParseResult::Ok(
|
ParseResult::Ok(declaration, next_pos) => Some(ParseResult::Ok(
|
||||||
@ -81,6 +89,15 @@ fn next_construct<'a>(
|
|||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
.or_else(|| match expression::try_parse(tokens, current_pos) {
|
||||||
|
ParseResult::Ok(expression, next_pos) => Some(ParseResult::Ok(
|
||||||
|
TopLevelDeclaration::Expression(expression),
|
||||||
|
next_pos,
|
||||||
|
)),
|
||||||
|
ParseResult::Err(_) => todo!(),
|
||||||
|
ParseResult::Mismatch(_) => todo!(),
|
||||||
|
ParseResult::Unmatched => todo!(),
|
||||||
|
})
|
||||||
.unwrap_or_else(|| ParseResult::Unmatched)
|
.unwrap_or_else(|| ParseResult::Unmatched)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +118,7 @@ mod tests {
|
|||||||
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
||||||
assert!(true)
|
assert!(true)
|
||||||
}
|
}
|
||||||
|
_ => panic!("Not implemented: Expression at top level"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +135,7 @@ mod tests {
|
|||||||
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
||||||
assert!(true)
|
assert!(true)
|
||||||
}
|
}
|
||||||
|
_ => panic!("Not implemented: Expression at top level"),
|
||||||
}
|
}
|
||||||
|
|
||||||
match declarations.get(1).unwrap() {
|
match declarations.get(1).unwrap() {
|
||||||
@ -124,6 +143,7 @@ mod tests {
|
|||||||
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
TopLevelDeclaration::FunctionDeclaration(_f) => {
|
||||||
assert!(true)
|
assert!(true)
|
||||||
}
|
}
|
||||||
|
_ => panic!("Not implemented: Expression at top level"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use super::{
|
|||||||
ParseResult,
|
ParseResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Statement, ()> {
|
pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> ParseResult<Statement> {
|
||||||
None.or_else(|| match binding::try_parse(tokens, pos) {
|
None.or_else(|| match binding::try_parse(tokens, pos) {
|
||||||
ParseResult::Ok(b, next) => Some(ParseResult::Ok(Statement::Binding(b), next)),
|
ParseResult::Ok(b, next) => Some(ParseResult::Ok(Statement::Binding(b), next)),
|
||||||
ParseResult::Err(err) => Some(ParseResult::Err(err)),
|
ParseResult::Err(err) => Some(ParseResult::Err(err)),
|
||||||
|
@ -33,7 +33,7 @@ impl Tokenizer for Vec<Token> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expects the token at `pos` to be of type `token_type`
|
/// Expects the token at `pos` to be of type `token_type`. Doesn't ignore whitespace or newlines
|
||||||
pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) -> Result3<&Token> {
|
pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) -> Result3<&Token> {
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
Some(t) if t.token_type == token_type => Result3::Ok(t),
|
Some(t) if t.token_type == token_type => Result3::Ok(t),
|
||||||
@ -45,6 +45,7 @@ pub fn try_token_type(tokens: &Vec<Token>, pos: usize, token_type: TokenType) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expects the token at `pos` to be an operator of value `operator`. Doesn't ignore whitespace or newlines
|
||||||
pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> {
|
pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result3<&Token> {
|
||||||
match tokens.get(pos) {
|
match tokens.get(pos) {
|
||||||
Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t),
|
Some(t) if t.token_type == TokenType::Operator && t.value == operator => Result3::Ok(t),
|
||||||
@ -56,12 +57,12 @@ pub fn try_operator(tokens: &Vec<Token>, pos: usize, operator: String) -> Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expects the token at `pos` to be of type `token_type`
|
/// Expects the token at `pos` to be of type `token_type`, ignoring all whitespace & newlines
|
||||||
pub fn parse_token_type(
|
pub fn parse_token_type(
|
||||||
tokens: &Vec<Token>,
|
tokens: &Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
token_type: TokenType,
|
token_type: TokenType,
|
||||||
) -> ParseResult<&Token, &Token> {
|
) -> ParseResult<&Token> {
|
||||||
let mut current_pos = pos;
|
let mut current_pos = pos;
|
||||||
|
|
||||||
// Ignore all whitespace and newlines
|
// Ignore all whitespace and newlines
|
||||||
@ -81,7 +82,7 @@ pub fn parse_token_type(
|
|||||||
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
|
Some(t) if t.token_type == TokenType::EOF || t.token_type == TokenType::NewLine => {
|
||||||
ParseResult::Unmatched
|
ParseResult::Unmatched
|
||||||
}
|
}
|
||||||
Some(t) => ParseResult::Mismatch(t),
|
Some(t) => ParseResult::Mismatch(t.clone()),
|
||||||
None => ParseResult::Unmatched,
|
None => ParseResult::Unmatched,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user