parser now bubbles errors instead of unit type
llvm added to dependencies
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
11
src/codegen/llvm_ir.rs
Normal 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
1
src/codegen/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod llvm_ir;
|
||||
@@ -29,4 +29,5 @@ else "else"
|
||||
let "let"
|
||||
:= "assign"
|
||||
Type "type"
|
||||
@main "main"
|
||||
\@main "main"
|
||||
[\n;] "linedelim"
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::io::ErrorKind::InvalidInput;
|
||||
|
||||
mod ast;
|
||||
mod errors;
|
||||
mod optimising;
|
||||
mod codegen;
|
||||
mod tests;
|
||||
|
||||
lrlex_mod!("lexers/fudge.l");
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
mod constfolding;
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user