parser now bubbles errors instead of unit type

llvm added to dependencies
This commit is contained in:
2025-10-28 12:28:50 +01:00
parent a0a6a15be3
commit 934d961be8
15 changed files with 132 additions and 67 deletions

View File

@@ -1,14 +1,27 @@
use std::fmt::Display;
use crate::ast::errors::ParsingErrorKind::InvalidLiteral;
pub struct ExpectedTokenError {
line: usize,
column_start: usize,
actual: &'static str,
expected: Vec<&'static str>,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct ParsingError {
pub kind: ParsingErrorKind,
pub line: usize,
pub column_start: usize,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum ParsingErrorKind {
InvalidLiteral,
UnexpectedToken {
expected: Vec<String>,
actual: String,
},
}
impl Display for ExpectedTokenError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "line {} column {}:\nExpected one of {} but got {}", self.line, self.column_start, self.expected.join(", "), self.actual)
impl ParsingError {
pub fn invalid_literal() -> ParsingError {
ParsingError {
kind: InvalidLiteral,
line: 0,
column_start: 0,
}
}
}
}

View File

@@ -1,19 +1,20 @@
pub fn parse_int(s: &str) -> Result<i64, ()> {
match s.parse::<i64>() {
Ok(val) => Ok(val),
Err(_) => {
eprintln!("{} cannot be represented as a i64", s);
Err(())
}
}
use crate::ast::errors::ParsingError;
use crate::ast::errors::ParsingErrorKind::InvalidLiteral;
use lrlex::DefaultLexeme;
use lrpar::Lexeme;
pub fn parse_int(s: &str) -> Result<i64, ParsingError> {
s.parse::<i64>().map_err(|_| ParsingError {
kind: InvalidLiteral,
line: 0,
column_start: 0,
})
}
pub fn parse_float(s: &str) -> Result<f64, ()> {
match s.parse::<f64>() {
Ok(val) => Ok(val),
Err(_) => {
eprintln!("{} cannot be represented as a f64", s);
Err(())
}
}
}
pub fn parse_float(s: &str) -> Result<f64, ParsingError> {
s.parse::<f64>().map_err(|_| ParsingError {
kind: InvalidLiteral,
line: 0,
column_start: 0,
})
}

View File

@@ -1,5 +1,5 @@
pub mod literal_parsers;
mod errors;
pub mod errors;
#[derive(Debug, Clone, PartialEq)]
pub struct Program {

11
src/codegen/llvm_ir.rs Normal file
View File

@@ -0,0 +1,11 @@
use crate::ast::Literal;
pub trait LLVMIRTranslation {
fn llvm_translate(&self) -> Result<String, ()>;
}
impl LLVMIRTranslation for crate::ast::Literal {
fn llvm_translate(&self) -> Result<String, ()> {
todo!()
}
}

1
src/codegen/mod.rs Normal file
View File

@@ -0,0 +1 @@
mod llvm_ir;

View File

@@ -29,4 +29,5 @@ else "else"
let "let"
:= "assign"
Type "type"
@main "main"
\@main "main"
[\n;] "linedelim"

View File

@@ -8,7 +8,7 @@ use std::io::ErrorKind::InvalidInput;
mod ast;
mod errors;
mod optimising;
mod codegen;
mod tests;
lrlex_mod!("lexers/fudge.l");

View File

@@ -1 +0,0 @@

View File

@@ -1 +0,0 @@
mod constfolding;

View File

@@ -1,40 +1,42 @@
%start Expr
%%
Expr -> Result<Expression, () >:
Expr -> Result<Expression, ParsingError >:
Expr "op_add" MulExpr { Ok(Expression::Add(Box::new( $1? ), Box::new( $3? ))) }
| Expr "op_sub" MulExpr { Ok(Expression::Sub(Box::new( $1? ), Box::new( $3? ))) }
| MulExpr { $1 }
;
MulExpr -> Result<Expression, () >:
MulExpr -> Result<Expression, ParsingError >:
MulExpr "op_mul" ConstExpr { Ok( Expression::Mul(Box::new($1?), Box::new($3?)) ) }
| MulExpr "op_div" ConstExpr { Ok( Expression::Div(Box::new($1?), Box::new($3?)) ) }
| MulExpr "op_mod" ConstExpr { Ok( Expression::Mod(Box::new($1?), Box::new($3?)) ) }
| ConstExpr { $1 }
;
ConstExpr -> Result<Expression, () >:
ConstExpr -> Result<Expression, ParsingError >:
'(' Expr ')' { $2 }
| 'lit_int' {
let v = $1.map_err( | _| ())?;
let v = $1.map_err( | _| ParsingError::invalid_literal() )?;
Ok(Expression::Lit(Literal::Int(parse_int( $lexer.span_str(v.span()))?)))
}
| "lit_float" {
let v = $1.map_err( | _| ())?;
Ok(Expression::Lit(Literal::Float(parse_float( $lexer.span_str(v.span()))?)))
let v = $1.map_err( | _| ParsingError::invalid_literal())?;
Ok(Expression::Lit(Literal::Float(parse_float($lexer.span_str(v.span()))?)))
}
| "ident" {
let v = $1.map_err( | _| ())?;
let v = $1.map_err( | _| ParsingError::invalid_literal())?;
Ok(Expression::Ident(String::from( $lexer.span_str(v.span()))))
}
;
%%
// Any functions here are in scope for all the grammar actions above.
use crate::ast::{Literal, Expression, Definition, StructDefinition, Program, TypedIdentifier, TypeArg,StructDefLiteral, TypeId};
use crate::ast::literal_parsers::*;
use crate::ast::errors::ParsingError;

View File

@@ -2,10 +2,10 @@
%%
program -> Result<Program, ()>:
program -> Result<Program, ParsingError>:
definitionlist maindef {
Ok(Program {
definition_list: $1?,
definition_list: $1.map_err(|_| ParsingError::invalid_literal())?,
main_def: $2?
})
@@ -18,8 +18,8 @@ program -> Result<Program, ()>:
}
;
maindef -> Result<Expression, ()>:
"main" "assign" Expr {$3}
maindef -> Result<Expression, ParsingError>:
"main" "assign" Expr "linedelim" {$3}
;
definitionlist -> Result<Vec<Definition>, ()>:
@@ -33,11 +33,11 @@ definitionlist -> Result<Vec<Definition>, ()>:
;
definition -> Result<Definition, ()>:
"let" "ident" "assign" Expr {
"let" "ident" "assign" Expr "linedelim" {
let v = $2.map_err(|_| ())?;
Ok(Definition::Binding {
name: String::from($lexer.span_str(v.span())),
value: $4?
value: $4.map_err(|_|())?
})
}
| "type" "ident" "assign" structdefliteral {
@@ -51,31 +51,32 @@ definition -> Result<Definition, ()>:
}
;
Expr -> Result<Expression, () >:
Expr -> Result<Expression, ParsingError >:
Expr "op_add" MulExpr { Ok(Expression::Add(Box::new( $1? ), Box::new( $3? ))) }
| Expr "op_sub" MulExpr { Ok(Expression::Sub(Box::new( $1? ), Box::new( $3? ))) }
| MulExpr { $1 }
;
MulExpr -> Result<Expression, () >:
MulExpr -> Result<Expression, ParsingError >:
MulExpr "op_mul" ConstExpr { Ok( Expression::Mul(Box::new($1?), Box::new($3?)) ) }
| MulExpr "op_div" ConstExpr { Ok( Expression::Div(Box::new($1?), Box::new($3?)) ) }
| MulExpr "op_mod" ConstExpr { Ok( Expression::Mod(Box::new($1?), Box::new($3?)) ) }
| ConstExpr { $1 }
;
ConstExpr -> Result<Expression, () >:
ConstExpr -> Result<Expression, ParsingError >:
'(' Expr ')' { $2 }
| 'lit_int' {
let v = $1.map_err( | _| ())?;
let v = $1.map_err( | _| ParsingError::invalid_literal() )?;
Ok(Expression::Lit(Literal::Int(parse_int( $lexer.span_str(v.span()))?)))
}
| "lit_float" {
let v = $1.map_err( | _| ())?;
Ok(Expression::Lit(Literal::Float(parse_float( $lexer.span_str(v.span()))?)))
let v = $1.map_err( | _| ParsingError::invalid_literal())?;
Ok(Expression::Lit(Literal::Float(parse_float($lexer.span_str(v.span()))?)))
}
| "ident" {
let v = $1.map_err( | _| ())?;
let v = $1.map_err( | _| ParsingError::invalid_literal())?;
Ok(Expression::Ident(String::from( $lexer.span_str(v.span()))))
}
;
@@ -117,6 +118,7 @@ typearg -> Result<TypeArg, ()>:
// Any functions here are in scope for all the grammar actions above.
use crate::ast::{Literal, Expression, Definition, StructDefinition, Program, TypedIdentifier, TypeArg,StructDefLiteral, TypeId};
use crate::ast::literal_parsers::*;
use crate::ast::errors::ParsingError;

View File

@@ -1,6 +1,7 @@
use lrlex::lrlex_mod;
use lrpar::lrpar_mod;
use crate::ast::errors::ParsingError;
use crate::ast::{Expression, Literal, Program};
lrlex_mod!("lexers/fudge.l");
@@ -21,19 +22,14 @@ macro_rules! test_literal_list {
};
}
fn parse_expr(input: &str) -> Result<Expression, ()> {
fn parse_expr(input: &str) -> Result<Expression, ParsingError> {
let lexerdef = expr_only_l::lexerdef();
let lexer = lexerdef.lexer(&input);
let (res, errs) = expr_only_y::parse(&lexer);
if let Some(parsed_res) = res {
parsed_res
} else {
Err(())
}
res.expect("REASON")
}
#[test]
fn test_int_literal() {
let matches_parsed_int = |s: &str| match parse_expr(s) {
Ok(i) => matches!(i, Expression::Lit(Literal::Int(_))),
Err(_) => false,