added boolean support
This commit is contained in:
parent
404916048a
commit
f165dad8f5
|
@ -7,6 +7,7 @@ name = "Yard"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -19,18 +20,77 @@ dependencies = [
|
||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.134"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
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]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -47,3 +107,9 @@ name = "regex-syntax"
|
||||||
version = "0.6.27"
|
version = "0.6.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "*"
|
regex = "*"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
rand = "0.8.5"
|
|
@ -3,3 +3,4 @@ Yard is an funny programming language compiler and interpreter written in pure R
|
||||||
It *will* contain features such as:
|
It *will* contain features such as:
|
||||||
1. a COMEFROM keyword (inverse goto)
|
1. a COMEFROM keyword (inverse goto)
|
||||||
2. a ```don't``` code block which never executes
|
2. a ```don't``` code block which never executes
|
||||||
|
3. swapped meaning of "" (for single characters) and '' (now for string literal)
|
|
@ -9,12 +9,10 @@ fn main() {
|
||||||
|
|
||||||
let source =
|
let source =
|
||||||
r"
|
r"
|
||||||
foo(c) = 3 * c
|
pi = 3.1415926
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
x = foo(5 * 6)
|
|
||||||
|
|
||||||
4 * 3
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ fn discover_exprs<'a>(functions: &mut Vec<Func<'a>>) {
|
||||||
/// parse a single term using a modified shunting yard
|
/// parse a single term using a modified shunting yard
|
||||||
fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, scope: &mut Scope) {
|
fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, scope: &mut Scope) {
|
||||||
let mut op_stack = vec![];
|
let mut op_stack = vec![];
|
||||||
let mut output = VecDeque::new();
|
let mut output = VecDeque::with_capacity(term.len());
|
||||||
|
|
||||||
'outer:
|
'outer:
|
||||||
while let Some(token) = term.pop_front() {
|
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();
|
let prec1 = op1.prec();
|
||||||
|
|
||||||
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
|
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
|
_ => break
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,17 @@ use std::collections::{VecDeque};
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
|
Or,
|
||||||
|
And,
|
||||||
|
Xor,
|
||||||
|
|
||||||
|
Eq,
|
||||||
|
Lt,
|
||||||
|
Gt,
|
||||||
|
GtEq,
|
||||||
|
LtEq,
|
||||||
|
NotEq,
|
||||||
|
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
|
@ -19,6 +30,17 @@ pub enum Assoc {
|
||||||
impl Operator {
|
impl Operator {
|
||||||
pub fn parse<'a>(str: &'a str) -> Self {
|
pub fn parse<'a>(str: &'a str) -> Self {
|
||||||
return match str {
|
return match str {
|
||||||
|
"|" => Operator::Or,
|
||||||
|
"&" => Operator::And,
|
||||||
|
"^" => Operator::Xor,
|
||||||
|
|
||||||
|
"==" => Operator::Eq,
|
||||||
|
"<" => Operator::Lt,
|
||||||
|
">" => Operator::Gt,
|
||||||
|
"<=" => Operator::LtEq,
|
||||||
|
">=" => Operator::GtEq,
|
||||||
|
"!=" => Operator::NotEq,
|
||||||
|
|
||||||
"+" => Operator::Add,
|
"+" => Operator::Add,
|
||||||
"-" => Operator::Sub,
|
"-" => Operator::Sub,
|
||||||
"*" => Operator::Mul,
|
"*" => Operator::Mul,
|
||||||
|
@ -31,6 +53,17 @@ impl Operator {
|
||||||
|
|
||||||
pub fn prec(&self) -> usize {
|
pub fn prec(&self) -> usize {
|
||||||
return match self {
|
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::Add => 3,
|
||||||
Operator::Sub => 3,
|
Operator::Sub => 3,
|
||||||
|
|
||||||
|
@ -62,9 +95,10 @@ pub enum Token<'a> {
|
||||||
Var(&'a str),
|
Var(&'a str),
|
||||||
Arg(&'a str),
|
Arg(&'a str),
|
||||||
Assign(&'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! {
|
lazy_static::lazy_static! {
|
||||||
static ref TOKEN_REGEX: regex::Regex = regex::Regex::new(TOKEN_REGEX_SRC).unwrap();
|
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 we have a match, save it as token
|
||||||
if let Some(mat) = group {
|
if let Some(mat) = group {
|
||||||
tokens.push_back(match i {
|
tokens.push_back(match i {
|
||||||
2 => Token::Assign(mat.as_str()),
|
2 => Token::Bool(parse_bool(mat.as_str())),
|
||||||
3 => Token::Word(mat.as_str()),
|
3 => Token::Assign(mat.as_str()),
|
||||||
4 => Token::Number(mat.as_str()),
|
4 => Token::Word(mat.as_str()),
|
||||||
5 => Token::Operator(Operator::parse(mat.as_str())),
|
5 => Token::Number(mat.as_str()),
|
||||||
6 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap()),
|
6 => Token::Operator(Operator::parse(mat.as_str())),
|
||||||
7 => Token::LineBreak,
|
7 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap()),
|
||||||
|
8 => Token::LineBreak,
|
||||||
|
|
||||||
_ => panic!("Unknown match to tokenize: {}", mat.as_str())
|
_ => panic!("Unknown match to tokenize: {}", mat.as_str())
|
||||||
});
|
});
|
||||||
|
@ -100,4 +135,13 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
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}")
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue