added grammar files
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
use crate::ast::expression::Expression;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/// A node that is evaluable to type `T`
|
||||||
|
pub trait Evaluable<T> {
|
||||||
|
fn evaluate(&self) -> T;
|
||||||
|
}
|
||||||
@@ -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>),
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
pub enum Literal {
|
||||||
|
Int(i64),
|
||||||
|
Float(f64),
|
||||||
|
Bool(bool),
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
mod evaluable;
|
||||||
|
pub mod literal;
|
||||||
|
pub mod expression;
|
||||||
|
pub mod logical;
|
||||||
|
mod comparison;
|
||||||
|
mod operators;
|
||||||
@@ -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,
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Expr := Identifier
|
||||||
|
| Expr Expr
|
||||||
|
| "&" Identifier "." Expr
|
||||||
|
| "(" Expr ")"
|
||||||
|
|
||||||
|
Declaration := Identifier ":=" Expr ";"
|
||||||
|
|
||||||
|
Abstraction := "&" Identifier "." Expr ";"
|
||||||
|
|
||||||
|
Application := Identifier "<|" Expr
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use crate::ast::literal::Literal;
|
||||||
|
|
||||||
grammar;
|
grammar;
|
||||||
|
|
||||||
pub Atom: f64 = {
|
pub Atom: Literal = {
|
||||||
<n:Int> => n as f64,
|
<n:Int> => Literal::Int(n),
|
||||||
Float,
|
<f: Float> => Literal::Float(f),
|
||||||
"(" <Atom> ")",
|
"(" <f: Atom> ")" => f,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub Int: i64 = <s:r"[0-9]|[1-9][0-9]*"> => i64::from_str(s).unwrap();
|
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 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;
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
use lalrpop_util::lalrpop_mod;
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod optimising;
|
mod optimising;
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
lalrpop_mod!(pub literals);
|
||||||
|
lalrpop_mod!(pub expressions);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
mod constfolding;
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
@@ -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()));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,57 +1,2 @@
|
|||||||
#[cfg(test)]
|
mod literals;
|
||||||
mod test {
|
mod expressions;
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user