added boolean support

This commit is contained in:
Sven Vogel 2022-10-05 13:10:29 +02:00
parent 404916048a
commit f165dad8f5
6 changed files with 126 additions and 14 deletions

66
Cargo.lock generated
View File

@ -7,6 +7,7 @@ name = "Yard"
version = "0.1.0"
dependencies = [
"lazy_static",
"rand",
"regex",
]
@ -19,18 +20,77 @@ dependencies = [
"memchr",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "regex"
version = "1.6.0"
@ -47,3 +107,9 @@ name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

View File

@ -8,3 +8,4 @@ edition = "2021"
[dependencies]
regex = "*"
lazy_static = "1.4.0"
rand = "0.8.5"

View File

@ -3,3 +3,4 @@ Yard is an funny programming language compiler and interpreter written in pure R
It *will* contain features such as:
1. a COMEFROM keyword (inverse goto)
2. a ```don't``` code block which never executes
3. swapped meaning of "" (for single characters) and '' (now for string literal)

View File

@ -9,12 +9,10 @@ fn main() {
let source =
r"
foo(c) = 3 * c
pi = 3.1415926
main() {
x = foo(5 * 6)
4 * 3
}
";

View File

@ -220,7 +220,7 @@ fn discover_exprs<'a>(functions: &mut Vec<Func<'a>>) {
/// parse a single term using a modified shunting yard
fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, scope: &mut Scope) {
let mut op_stack = vec![];
let mut output = VecDeque::new();
let mut output = VecDeque::with_capacity(term.len());
'outer:
while let Some(token) = term.pop_front() {
@ -273,8 +273,10 @@ fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, scope: &mut Scope) {
let prec1 = op1.prec();
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
output.push_back(op_stack.pop().unwrap())
output.push_back(op_stack.pop().unwrap());
continue
}
break
},
_ => break
}

View File

@ -2,6 +2,17 @@ use std::collections::{VecDeque};
#[derive(Debug, Hash, PartialEq, Eq)]
pub enum Operator {
Or,
And,
Xor,
Eq,
Lt,
Gt,
GtEq,
LtEq,
NotEq,
Add,
Sub,
Mul,
@ -19,6 +30,17 @@ pub enum Assoc {
impl Operator {
pub fn parse<'a>(str: &'a str) -> Self {
return match str {
"|" => Operator::Or,
"&" => Operator::And,
"^" => Operator::Xor,
"==" => Operator::Eq,
"<" => Operator::Lt,
">" => Operator::Gt,
"<=" => Operator::LtEq,
">=" => Operator::GtEq,
"!=" => Operator::NotEq,
"+" => Operator::Add,
"-" => Operator::Sub,
"*" => Operator::Mul,
@ -31,6 +53,17 @@ impl Operator {
pub fn prec(&self) -> usize {
return match self {
Operator::Eq => 2,
Operator::Lt => 2,
Operator::Gt => 2,
Operator::LtEq => 2,
Operator::GtEq => 2,
Operator::NotEq => 2,
Operator::Or => 0,
Operator::Xor => 0,
Operator::And => 1,
Operator::Add => 3,
Operator::Sub => 3,
@ -62,9 +95,10 @@ pub enum Token<'a> {
Var(&'a str),
Arg(&'a str),
Assign(&'a str),
Bool(bool),
}
const TOKEN_REGEX_SRC: &'static str = r"(#.*)|([A-Za-z_]+)\s*=|([A-Za-z_]+)|(\d*\.?\d+)|([+\-*/=])|([(){}])|(\n)";
const TOKEN_REGEX_SRC: &'static str = r"(#.*)|(true|false|yes|no|maybe)|([A-Za-z_]+)\s*=|([A-Za-z_]+)|(\d*\.?\d+)|(!=|==|<=|<=|[&|+\-*/<>])|([(){}])|(\n)";
lazy_static::lazy_static! {
static ref TOKEN_REGEX: regex::Regex = regex::Regex::new(TOKEN_REGEX_SRC).unwrap();
@ -86,12 +120,13 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
// if we have a match, save it as token
if let Some(mat) = group {
tokens.push_back(match i {
2 => Token::Assign(mat.as_str()),
3 => Token::Word(mat.as_str()),
4 => Token::Number(mat.as_str()),
5 => Token::Operator(Operator::parse(mat.as_str())),
6 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap()),
7 => Token::LineBreak,
2 => Token::Bool(parse_bool(mat.as_str())),
3 => Token::Assign(mat.as_str()),
4 => Token::Word(mat.as_str()),
5 => Token::Number(mat.as_str()),
6 => Token::Operator(Operator::parse(mat.as_str())),
7 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap()),
8 => Token::LineBreak,
_ => panic!("Unknown match to tokenize: {}", mat.as_str())
});
@ -101,3 +136,12 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
return tokens;
}
fn parse_bool(text: &str) -> bool {
return match text.to_ascii_lowercase().as_str() {
"true" | "ye" => true,
"false" |"no" => false,
"maybe" => rand::random(),
_ => panic!("Not a recognized boolean {text}")
}
}