2019-08-14 07:25:45 -07:00
|
|
|
use std::rc::Rc;
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
2019-08-15 06:28:40 -07:00
|
|
|
use crate::tokenizing::TokenKind;
|
2019-08-14 07:25:45 -07:00
|
|
|
use crate::builtin::Builtin;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
pub struct PrefixOp {
|
2019-09-10 03:40:41 -07:00
|
|
|
sigil: Rc<String>,
|
2019-08-14 07:25:45 -07:00
|
|
|
pub builtin: Option<Builtin>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PrefixOp {
|
2019-09-10 03:40:41 -07:00
|
|
|
#[allow(dead_code)]
|
2019-08-14 07:25:45 -07:00
|
|
|
pub fn sigil(&self) -> &Rc<String> {
|
|
|
|
&self.sigil
|
|
|
|
}
|
|
|
|
pub fn is_prefix(op: &str) -> bool {
|
|
|
|
match op {
|
|
|
|
"+" => true,
|
|
|
|
"-" => true,
|
|
|
|
"!" => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for PrefixOp {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
use Builtin::*;
|
|
|
|
|
|
|
|
let builtin = match s {
|
|
|
|
"+" => Ok(Increment),
|
|
|
|
"-" => Ok(Negate),
|
|
|
|
"!" => Ok(BooleanNot),
|
|
|
|
_ => Err(())
|
|
|
|
};
|
|
|
|
|
|
|
|
builtin.map(|builtin| PrefixOp { sigil: Rc::new(s.to_string()), builtin: Some(builtin) })
|
|
|
|
}
|
|
|
|
}
|
2019-08-15 06:28:40 -07:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
pub struct BinOp {
|
|
|
|
sigil: Rc<String>,
|
|
|
|
pub builtin: Option<Builtin>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BinOp {
|
|
|
|
pub fn from_sigil(sigil: &str) -> BinOp {
|
|
|
|
let builtin = Builtin::from_str(sigil).ok();
|
|
|
|
BinOp { sigil: Rc::new(sigil.to_string()), builtin }
|
|
|
|
}
|
|
|
|
pub fn sigil(&self) -> &Rc<String> {
|
|
|
|
&self.sigil
|
|
|
|
}
|
|
|
|
pub fn from_sigil_token(tok: &TokenKind) -> Option<BinOp> {
|
|
|
|
let s = token_kind_to_sigil(tok)?;
|
|
|
|
Some(BinOp::from_sigil(s))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn min_precedence() -> i32 {
|
|
|
|
i32::min_value()
|
|
|
|
}
|
|
|
|
pub fn get_precedence_from_token(op_tok: &TokenKind) -> Option<i32> {
|
|
|
|
let s = token_kind_to_sigil(op_tok)?;
|
|
|
|
Some(binop_precedences(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn token_kind_to_sigil<'a>(tok: &'a TokenKind) -> Option<&'a str> {
|
|
|
|
use self::TokenKind::*;
|
|
|
|
Some(match tok {
|
|
|
|
Operator(op) => op.as_str(),
|
|
|
|
Period => ".",
|
|
|
|
Pipe => "|",
|
|
|
|
Slash => "/",
|
|
|
|
LAngleBracket => "<",
|
|
|
|
RAngleBracket => ">",
|
|
|
|
Equals => "=",
|
|
|
|
_ => return None
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn binop_precedences(s: &str) -> i32 {
|
|
|
|
let default = 10_000_000;
|
|
|
|
match s {
|
|
|
|
"+" => 10,
|
|
|
|
"-" => 10,
|
|
|
|
"*" => 20,
|
|
|
|
"/" => 20,
|
|
|
|
"%" => 20,
|
|
|
|
"++" => 30,
|
|
|
|
"^" => 30,
|
|
|
|
"&" => 20,
|
|
|
|
"|" => 20,
|
|
|
|
">" => 20,
|
|
|
|
">=" => 20,
|
|
|
|
"<" => 20,
|
|
|
|
"<=" => 20,
|
|
|
|
"==" => 40,
|
|
|
|
"=" => 10,
|
|
|
|
"<=>" => 30,
|
|
|
|
_ => default,
|
|
|
|
}
|
|
|
|
}
|