Handle prefixes better

This commit is contained in:
Tiffany Bennett 2016-08-03 00:01:18 -04:00
parent ba948c7ae8
commit 4cc6fd4e59
2 changed files with 29 additions and 38 deletions

View file

@ -11,7 +11,7 @@ pub struct Context {
dimensions: Vec<String>,
units: HashMap<String, Value>,
aliases: HashMap<Unit, String>,
prefixes: Vec<(String, f64)>,
prefixes: Vec<(String, Value)>,
}
impl Value {
@ -143,11 +143,10 @@ impl Context {
return Some(v)
}
}
for &(ref pre, value) in &self.prefixes {
for &(ref pre, ref value) in &self.prefixes {
if name.starts_with(pre) {
if let Some(mut v) = self.lookup(&name[pre.len()..]) {
v.0 *= value;
return Some(v)
if let Some(v) = self.lookup(&name[pre.len()..]) {
return Some(v.mul(&value))
}
}
}
@ -201,9 +200,11 @@ impl Context {
dimensions: Vec::new(),
units: HashMap::new(),
aliases: HashMap::new(),
prefixes: defs.prefixes,
prefixes: Vec::new(),
};
ctx.prefixes.sort_by(|a, b| a.0.cmp(&b.0));
for (name, def) in defs.defs {
match *def {
Def::Dimension(ref name) => {
@ -215,6 +216,19 @@ impl Context {
},
Err(e) => println!("Unit {} is malformed: {}", name, e)
},
Def::Prefix(ref expr) => match ctx.eval(expr) {
Ok(v) => {
ctx.prefixes.push((name.clone(), v));
},
Err(e) => println!("Prefix {} is malformed: {}", name, e)
},
Def::SPrefix(ref expr) => match ctx.eval(expr) {
Ok(v) => {
ctx.prefixes.push((name.clone(), v.clone()));
ctx.units.insert(name.clone(), v);
},
Err(e) => println!("Prefix {} is malformed: {}", name, e)
},
Def::Error(ref err) => println!("Def {}: {}", name, err),
};
}
@ -228,8 +242,6 @@ impl Context {
}
}
ctx.prefixes.sort_by(|a, b| a.0.cmp(&b.0));
ctx
}
}

View file

@ -175,7 +175,7 @@ impl<'a> Iterator for TokenIterator<'a> {
pub type Iter<'a> = Peekable<TokenIterator<'a>>;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Expr {
Unit(String),
Const(f64),
@ -190,6 +190,8 @@ pub enum Expr {
#[derive(Debug)]
pub enum Def {
Dimension(String),
Prefix(Expr),
SPrefix(Expr),
Unit(Expr),
Error(String),
}
@ -198,7 +200,6 @@ pub enum Def {
pub struct Defs {
pub defs: Vec<(String, Rc<Def>)>,
pub aliases: Vec<(Expr, String)>,
pub prefixes: Vec<(String, f64)>,
}
fn parse_term(mut iter: &mut Iter) -> Expr {
@ -293,7 +294,6 @@ fn parse_alias(mut iter: &mut Iter) -> Option<(Expr, String)> {
pub fn parse(mut iter: &mut Iter) -> Defs {
let mut map = vec![];
let mut aliases = vec![];
let mut prefixes = vec![];
loop {
let mut copy = iter.clone();
if let Some(a) = parse_alias(&mut copy) {
@ -307,33 +307,13 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
Token::Eof => break,
Token::Ident(name) => {
let def = match iter.next().unwrap() {
Token::ColonDash => match iter.next().unwrap() {
Token::Number(n) => {
prefixes.push((name, n));
continue
},
Token::Ident(ref n) => {
let mut found = None;
for &(ref n2, value) in &prefixes {
if n == n2 {
found = Some(value);
break;
}
}
if let Some(found) = found {
prefixes.push((name, found));
continue
}
Def::Error(format!("No such prefix {}", n))
},
x => Def::Error(format!("Expected number, got {:?}", x))
Token::ColonDash => {
let expr = parse_expr(iter);
Def::Prefix(expr)
},
Token::DColonDash => match iter.next().unwrap() {
Token::Number(n) => {
prefixes.push((name.clone(), n));
Def::Unit(Expr::Const(n))
},
x => Def::Error(format!("Expected number, got {:?}", x))
Token::DColonDash => {
let expr = parse_expr(iter);
Def::SPrefix(expr)
},
Token::EqBangEq => match iter.next().unwrap() {
Token::Ident(val) => Def::Dimension(val),
@ -371,7 +351,6 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
Defs {
defs: map,
aliases: aliases,
prefixes: prefixes,
}
}