added grammar files

This commit is contained in:
2025-10-20 20:22:01 +02:00
parent a9044f62f4
commit df48d271e2
14 changed files with 168 additions and 62 deletions

View File

@@ -0,0 +1 @@
use crate::ast::expression::Expression;

View File

@@ -0,0 +1,4 @@
/// A node that is evaluable to type `T`
pub trait Evaluable<T> {
fn evaluate(&self) -> T;
}

View File

@@ -0,0 +1,23 @@
use crate::ast::literal::Literal;
pub enum Expression {
Identifier(String),
Literal(Literal),
Addition(Box<Expression>, Box<Expression>),
Subtraction(Box<Expression>, Box<Expression>),
Multiplication(Box<Expression>, Box<Expression>),
Division(Box<Expression>, Box<Expression>),
Remainder(Box<Expression>, Box<Expression>),
Negation(Box<Expression>),
And(Box<Expression>, Box<Expression>),
Or(Box<Expression>, Box<Expression>),
Equal(Box<Expression>, Box<Expression>),
NotEqual(Box<Expression>, Box<Expression>),
Less(Box<Expression>, Box<Expression>),
LessEqual(Box<Expression>, Box<Expression>),
Greater(Box<Expression>, Box<Expression>),
GreaterEqual(Box<Expression>, Box<Expression>),
}

View File

@@ -0,0 +1,5 @@
pub enum Literal {
Int(i64),
Float(f64),
Bool(bool),
}

View File

@@ -0,0 +1,6 @@
mod evaluable;
pub mod literal;
pub mod expression;
pub mod logical;
mod comparison;
mod operators;

View File

@@ -0,0 +1,30 @@
use crate::ast::expression::Expression;
pub enum Operator {
Unary(UnaryOperator),
Binary(BinaryOperator),
}
pub enum UnaryOperator {
Minus,
Not,
Reference,
Dereference,
}
pub enum BinaryOperator {
Plus,
Minus,
Multiply,
Divide,
Modulo,
And,
Or,
Xor,
Equal,
NotEqual,
Greater,
GreaterEqual,
Less,
LessEqual,
}

View File

@@ -0,0 +1,9 @@
use crate::ast::expression::Expression;
grammar;
pub ASTExpression: Expression = {
<s: Identifier> => Expression::Identifier(String::from(s)),
};
pub Identifier: &'input str = <s:r"[_a-zA-Z][_a-zA-Z0-9]*"> => s;

View File

@@ -0,0 +1,10 @@
Expr := Identifier
| Expr Expr
| "&" Identifier "." Expr
| "(" Expr ")"
Declaration := Identifier ":=" Expr ";"
Abstraction := "&" Identifier "." Expr ";"
Application := Identifier "<|" Expr

View File

@@ -1,13 +1,14 @@
use std::str::FromStr;
use crate::ast::literal::Literal;
grammar;
pub Atom: f64 = {
<n:Int> => n as f64,
Float,
"(" <Atom> ")",
pub Atom: Literal = {
<n:Int> => Literal::Int(n),
<f: Float> => Literal::Float(f),
"(" <f: Atom> ")" => f,
};
pub Int: i64 = <s:r"[0-9]|[1-9][0-9]*"> => i64::from_str(s).unwrap();
pub Float: f64 = <s:r"[+-]?([0-9]*[.][0-9]+|[0-9]*([.][0-9]+)?[Ee][+-]?[1-9][0-9]*)"> => f64::from_str(s).unwrap();
pub StringLiteral: &'input str = <s:"\"[^\"]\""> => s;
//pub StringLiteral: &'input str = <s:"\"[^\"]\""> => s;

View File

@@ -1,5 +1,11 @@
use lalrpop_util::lalrpop_mod;
mod ast;
mod optimising;
mod tests;
lalrpop_mod!(pub literals);
lalrpop_mod!(pub expressions);
fn main() {
println!("Hello, world!");

View File

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

View File

@@ -0,0 +1,16 @@
#[test]
fn identifiers() {
use crate::expressions::IdentifierParser as IdentParser;
assert!(IdentParser::new().parse("a").is_ok());
assert!(IdentParser::new().parse("_").is_ok());
assert!(IdentParser::new().parse("a_a_a_").is_ok());
assert!(IdentParser::new().parse("_0").is_ok());
assert!(IdentParser::new().parse("_a").is_ok());
assert!(IdentParser::new().parse("__").is_ok());
assert!(IdentParser::new().parse("0").is_err());
assert!(IdentParser::new().parse("0123456").is_err());
assert!(IdentParser::new().parse("0aaaa").is_err());
}

View File

@@ -0,0 +1,49 @@
use crate::literals::AtomParser as Parser;
use std::any::type_name_of_val;
use std::convert::identity;
#[test]
fn int_literals() {
let parser = Parser::new();
let valid_ints = vec!["1234567890", "(1234567890)", "((((1))))"];
let invalid_ints = vec!["01", "(1", "6543)", "((987652345)"];
assert!(valid_ints.into_iter().all(|s| parser.parse(s).is_ok()));
assert!(invalid_ints.into_iter().all(|s| parser.parse(s).is_err()));
}
#[test]
fn test_float_dots() {
let valid_floats = vec![
"0.0",
"-0.0",
"3.141592653589793",
"-1.123456765432123456789",
];
assert!(Parser::new().parse("1.1").is_ok());
assert!(Parser::new().parse("-1.1").is_ok());
assert!(Parser::new().parse(".1").is_ok());
assert!(Parser::new().parse("-.1").is_ok());
}
#[test]
fn test_float_exps() {
let parser = crate::literals::FloatParser::new();
let valid_float_exps: Vec<&str> = vec![
"1e1", "-1e1", "1e-1", "-1e-1", "1.1e1", "1.1e-1", "-1.1e1", "-1.1e-1", ".1e1", "-.1e1",
"-.1e-1", "1E1", "-1E1", "1E-1", "-1E-1", "1.1E1", "1.1E-1", "-1.1E1", "-1.1E-1", ".1E1",
"-.1E1", "-.1E-1",
];
let invalid_float_exps: Vec<&str> = vec!["AAAAAAAAAAAAAAA", "1.e1", "1e1.1", "1.1e1.1", "-1e1.1", "1e-1.1"];
assert!(
valid_float_exps
.into_iter()
.all(|s| parser.parse(s).is_ok())
);
assert!(invalid_float_exps
.into_iter()
.all(|s| parser.parse(s).is_err()));
}

View File

@@ -1,57 +1,2 @@
#[cfg(test)]
mod test {
use crate::grammar;
use grammar::AtomParser as Parser;
#[test]
fn int_literals() {
assert!(Parser::new().parse("22").is_ok());
assert!(Parser::new().parse("(22)").is_ok());
assert!(Parser::new().parse("((22))").is_ok());
}
#[test]
fn test_float_dots() {
assert!(Parser::new().parse("1.1").is_ok());
assert!(Parser::new().parse("-1.1").is_ok());
assert!(Parser::new().parse(".1").is_ok());
assert!(Parser::new().parse("-.1").is_ok());
}
#[test]
fn test_float_exps() {
assert!(Parser::new().parse("(1e1)").is_ok());
assert!(Parser::new().parse("(-1e1)").is_ok());
assert!(Parser::new().parse("(1e-1)").is_ok());
assert!(Parser::new().parse("(-1e-1)").is_ok());
assert!(Parser::new().parse("(1E1)").is_ok());
assert!(Parser::new().parse("(-1E1)").is_ok());
assert!(Parser::new().parse("(1E-1)").is_ok());
assert!(Parser::new().parse("(-1E-1)").is_ok());
assert!(Parser::new().parse("(1.1e1)").is_ok());
assert!(Parser::new().parse("(-1.1e1)").is_ok());
assert!(Parser::new().parse("(1.1e-1)").is_ok());
assert!(Parser::new().parse("(-1.1e-1)").is_ok());
assert!(Parser::new().parse("(1.1E1)").is_ok());
assert!(Parser::new().parse("(-1.1E1)").is_ok());
assert!(Parser::new().parse("(1.1E-1)").is_ok());
assert!(Parser::new().parse("(-1.1E-1)").is_ok());
assert!(Parser::new().parse("(1.0e1)").is_ok());
assert!(Parser::new().parse("(-0.1e1)").is_ok());
assert!(Parser::new().parse("(1.0e-1)").is_ok());
assert!(Parser::new().parse("(-1.0e-1)").is_ok());
assert!(Parser::new().parse("(1.E1)").is_err());
assert!(Parser::new().parse("(-1E1)").is_ok());
assert!(Parser::new().parse("(1E-10)").is_ok());
assert!(Parser::new().parse("(-1E-1)").is_ok());
assert!(Parser::new().parse("(1.1e1)").is_ok());
assert!(Parser::new().parse("(-1.1e1)").is_ok());
assert!(Parser::new().parse("(1.1e-1)").is_ok());
assert!(Parser::new().parse("(-1.1e-1)").is_ok());
assert!(Parser::new().parse("(1.1E1)").is_ok());
assert!(Parser::new().parse("(-1.1E1)").is_ok());
assert!(Parser::new().parse("(1.1E-1)").is_ok());
assert!(Parser::new().parse("(-1.1E-1)").is_ok());
assert!(Parser::new().parse("FOOBAR").is_err());
}
}
mod literals;
mod expressions;