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

49
Cargo.lock generated
View File

@@ -32,6 +32,12 @@ dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
[[package]]
name = "bitflags"
version = "2.9.4"
@@ -86,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
dependencies = [
"cfg-if",
"libc",
"libc 0.2.177",
"libredox",
"windows-sys",
]
@@ -102,10 +108,17 @@ name = "fudgerust2"
version = "0.1.0"
dependencies = [
"cfgrammar",
"llvm-sys",
"lrlex",
"lrpar",
]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]]
name = "getopts"
version = "0.2.24"
@@ -143,6 +156,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.177"
@@ -155,11 +174,23 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
dependencies = [
"bitflags",
"libc",
"bitflags 2.9.4",
"libc 0.2.177",
"redox_syscall",
]
[[package]]
name = "llvm-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5e8322ae48d7a8831627ca58aeb0601f97d7e4119d6c733118c4a3ea2c04e29"
dependencies = [
"bitflags 0.3.3",
"gcc",
"libc 0.1.12",
"semver",
]
[[package]]
name = "lrlex"
version = "0.13.10"
@@ -241,7 +272,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
"libc 0.2.177",
]
[[package]]
@@ -284,7 +315,7 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
"bitflags 2.9.4",
]
[[package]]
@@ -322,6 +353,12 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
[[package]]
name = "serde"
version = "1.0.228"
@@ -389,7 +426,7 @@ checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [
"deranged",
"itoa",
"libc",
"libc 0.2.177",
"num-conv",
"num_threads",
"powerfmt",

View File

@@ -14,3 +14,4 @@ lrpar = "0.13.10"
cfgrammar = "0.13.10"
lrlex = "0.13.10"
lrpar = "0.13.10"
llvm-sys = "0.2.1"

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( | _| ())?;
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( | _| ())?;
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,

View File

@@ -1 +1,3 @@
13 / 14 % 17 *
let a := 1
@main := a