mirror of
https://github.com/tiffany352/rink-rs
synced 2024-09-20 22:21:57 +00:00
Introduce quantity syntax to gnu units definitions
This commit is contained in:
parent
ef2362f6bc
commit
920fffe9ca
6 changed files with 94 additions and 98 deletions
|
@ -476,30 +476,30 @@ Hz hertz
|
|||
# "You want:" prompt to tell the user the dimension of the unit.
|
||||
#
|
||||
|
||||
LENGTH meter
|
||||
AREA LENGTH^2
|
||||
VOLUME LENGTH^3
|
||||
MASS kilogram
|
||||
CURRENT ampere
|
||||
AMOUNT mole
|
||||
ANGLE radian
|
||||
SOLID_ANGLE steradian
|
||||
MONEY US$
|
||||
FORCE newton
|
||||
PRESSURE FORCE / AREA
|
||||
STRESS FORCE / AREA
|
||||
CHARGE coulomb
|
||||
CAPACITANCE farad
|
||||
RESISTANCE ohm
|
||||
CONDUCTANCE siemens
|
||||
INDUCTANCE henry
|
||||
FREQUENCY hertz
|
||||
VELOCITY LENGTH / TIME
|
||||
ACCELERATION VELOCITY / TIME
|
||||
DENSITY MASS / VOLUME
|
||||
LINEAR_DENSITY MASS / LENGTH
|
||||
VISCOSITY FORCE TIME / AREA
|
||||
KINEMATIC_VISCOSITY VISCOSITY / DENSITY
|
||||
length ? meter
|
||||
area ? length^2
|
||||
volume ? length^3
|
||||
mass ? kilogram
|
||||
current ? ampere
|
||||
amount ? mole
|
||||
angle ? radian
|
||||
solid_angle ? steradian
|
||||
money ? US$
|
||||
force ? newton
|
||||
pressure ? force / area
|
||||
stress ? force / area
|
||||
charge ? coulomb
|
||||
capacitance ? farad
|
||||
resistance ? ohm
|
||||
conductance ? siemens
|
||||
inductance ? henry
|
||||
frequency ? hertz
|
||||
velocity ? length / time
|
||||
acceleration ? velocity / time
|
||||
density ? mass / volume
|
||||
linear_density ? mass / length
|
||||
viscosity ? force time / area
|
||||
kinematic_viscosity ? viscosity / density
|
||||
|
||||
|
||||
#
|
||||
|
@ -737,8 +737,8 @@ fine 1|1000 # Measure of gold purity
|
|||
# with "temp".
|
||||
#
|
||||
|
||||
TEMPERATURE kelvin
|
||||
TEMPERATURE_DIFFERENCE kelvin
|
||||
temperature ? kelvin
|
||||
temperature_difference kelvin
|
||||
|
||||
# In 1741 Anders Celsius introduced a temperature scale with water boiling at
|
||||
# 0 degrees and freezing at 100 degrees at standard pressure. After his death
|
||||
|
@ -1260,11 +1260,10 @@ ozcu ouncecopper # in circuitboard fabrication
|
|||
# Photometric units
|
||||
#
|
||||
|
||||
LUMINOUS_INTENSITY candela
|
||||
LUMINOUS_FLUX lumen
|
||||
LUMINOUS_ENERGY talbot
|
||||
ILLUMINANCE lux
|
||||
EXITANCE lux
|
||||
luminous_intensity ? candela
|
||||
luminous_flux ? lumen
|
||||
luminous_energy ? talbot
|
||||
illuminance ? lux
|
||||
|
||||
candle 1.02 candela # Standard unit for luminous intensity
|
||||
hefnerunit 0.9 candle # in use before candela
|
||||
|
@ -1300,7 +1299,7 @@ skot 1e-3 apostilb # measurements relating to dark adapted
|
|||
# eyes.
|
||||
# Luminance measures
|
||||
|
||||
LUMINANCE nit
|
||||
luminance ? nit
|
||||
|
||||
nit cd/m^2 # Luminance: the intensity per projected
|
||||
stilb cd / cm^2 # area of an extended luminous source.
|
||||
|
@ -1579,7 +1578,7 @@ C_illum C_apex1961
|
|||
# and a description of how to compute the correction to mean time.
|
||||
#
|
||||
|
||||
TIME second
|
||||
time ? second
|
||||
|
||||
anomalisticyear 365.2596 days # The time between successive
|
||||
# perihelion passages of the
|
||||
|
@ -2895,8 +2894,7 @@ count /pound # For measuring the size of shrimp
|
|||
# Other units of work, energy, power, etc
|
||||
#
|
||||
|
||||
ENERGY joule
|
||||
WORK joule
|
||||
energy ? joule
|
||||
|
||||
# Calories: energy to raise a gram of water one degree celsius
|
||||
|
||||
|
@ -3085,7 +3083,7 @@ uranium_natural 0.7% uranium_pure # Natural uranium: 0.7% U-235
|
|||
celsiusheatunit cal lb K / gram K
|
||||
chu celsiusheatunit
|
||||
|
||||
POWER watt
|
||||
power ? watt
|
||||
|
||||
# "Apparent" average power in an AC circuit, the product of rms voltage
|
||||
# and rms current, equal to the true power in watts when voltage and
|
||||
|
@ -3119,24 +3117,24 @@ chevalvapeur metrichorsepower
|
|||
# cross sectional area, t is the time, and L is the length (thickness).
|
||||
# Thermal conductivity is a material property.
|
||||
|
||||
THERMAL_CONDUCTIVITY POWER / AREA (TEMPERATURE_DIFFERENCE/LENGTH)
|
||||
THERMAL_RESISTIVITY 1/THERMAL_CONDUCTIVITY
|
||||
thermal_conductivity ? power / area (temperature_difference/length)
|
||||
thermal_resistivity ? 1/thermal_conductivity
|
||||
|
||||
# Thermal conductance is the rate at which heat flows across a given
|
||||
# object, so the area and thickness have been fixed. It depends on
|
||||
# the size of the object and is hence not a material property.
|
||||
|
||||
THERMAL_CONDUCTANCE POWER / TEMPERATURE_DIFFERENCE
|
||||
THERMAL_RESISTANCE 1/THERMAL_CONDUCTANCE
|
||||
thermal_conductance ? power / temperature_difference
|
||||
thermal_resistance ? 1/thermal_conductance
|
||||
|
||||
# Thermal admittance is the rate of heat flow per area across an
|
||||
# object whose thickness has been fixed. Its reciprocal, thermal
|
||||
# insulation, is used to for measuring the heat transfer per area
|
||||
# of sheets of insulation or cloth that are of specified thickness.
|
||||
|
||||
THERMAL_ADMITTANCE THERMAL_CONDUCTIVITY / LENGTH
|
||||
THERMAL_INSULANCE THERMAL_RESISTIVITY LENGTH
|
||||
THERMAL_INSULATION THERMAL_RESISTIVITY LENGTH
|
||||
thermal_admittance ? thermal_conductivity / length
|
||||
thermal_insulance ? thermal_resistivity length
|
||||
thermal_insulation ? thermal_resistivity length
|
||||
|
||||
Rvalue degR ft^2 hr / btu
|
||||
Uvalue 1/Rvalue
|
||||
|
@ -3202,7 +3200,7 @@ tog 0.1 K m^2 / W # Also used for clothing.
|
|||
|
||||
# Misc other measures
|
||||
|
||||
ENTROPY ENERGY / TEMPERATURE
|
||||
entropy ? energy / temperature
|
||||
clausius 1e3 cal/K # A unit of physical entropy
|
||||
langley thermcalorie/cm^2 # Used in radiation theory
|
||||
poncelet 100 kg force m / s
|
||||
|
@ -3563,7 +3561,7 @@ grobe_sabon 84 didotpoint
|
|||
# to measure information and as a physical quantity.
|
||||
#
|
||||
|
||||
INFORMATION bit
|
||||
information ? bit
|
||||
|
||||
#nat (1/ln(2)) bits # Entropy measured base e
|
||||
#hartley log2(10) bits # Entropy of a uniformly
|
||||
|
@ -3678,7 +3676,7 @@ semitone octave^(1|12)
|
|||
#
|
||||
|
||||
wholenote !
|
||||
MUSICAL_NOTE_LENGTH wholenote
|
||||
musical_note_length ? wholenote
|
||||
halfnote 1|2 wholenote
|
||||
quarternote 1|4 wholenote
|
||||
eighthnote 1|8 wholenote
|
||||
|
@ -3965,7 +3963,7 @@ lbcut poundcut
|
|||
# Gas and Liquid flow units
|
||||
#
|
||||
|
||||
FLUID_FLOW VOLUME / TIME
|
||||
#FLUID_FLOW VOLUME / TIME
|
||||
|
||||
# Some obvious volumetric gas flow units (cu is short for cubic)
|
||||
|
||||
|
@ -4025,7 +4023,7 @@ sverdrup 1e6 m^3 / sec # Used to express flow of ocean
|
|||
# of gas molecules per unit time, and hence to the mass flow if the
|
||||
# molecular mass is known.
|
||||
|
||||
GAS_FLOW PRESSURE FLUID_FLOW
|
||||
#GAS_FLOW PRESSURE FLUID_FLOW
|
||||
|
||||
sccm atm cc/min # 's' is for "standard" to indicate
|
||||
sccs atm cc/sec # flow at standard pressure
|
||||
|
@ -4751,7 +4749,7 @@ Ci curie # emitted by the amount of radon that is
|
|||
# in equilibrium with 1 gram of radium.
|
||||
rutherford 1e6 Bq #
|
||||
|
||||
RADIATION_DOSE gray
|
||||
radiation_dose ? gray
|
||||
gray J/kg # Absorbed dose of radiation
|
||||
Gy gray #
|
||||
rad 1e-2 Gy # From Radiation Absorbed Dose
|
||||
|
|
|
@ -64,6 +64,7 @@ pub enum Def {
|
|||
Prefix(Expr),
|
||||
SPrefix(Expr),
|
||||
Unit(Expr),
|
||||
Quantity(Expr),
|
||||
DatePattern(Vec<DatePattern>),
|
||||
Error(String),
|
||||
}
|
||||
|
@ -71,5 +72,4 @@ pub enum Def {
|
|||
#[derive(Debug)]
|
||||
pub struct Defs {
|
||||
pub defs: Vec<(String, Rc<Def>)>,
|
||||
pub aliases: Vec<(Expr, String)>,
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ fn main() {
|
|||
Token::Plus => print!("+"),
|
||||
Token::Dash => print!("-"),
|
||||
Token::Asterisk => print!("*"),
|
||||
Token::Question => print!("?"),
|
||||
Token::Error(e) => print!("<error: {}>", e),
|
||||
}
|
||||
}
|
||||
|
|
66
src/eval.rs
66
src/eval.rs
|
@ -160,26 +160,27 @@ impl Context {
|
|||
return Some(Number::one_unit(k.to_owned()))
|
||||
}
|
||||
}
|
||||
self.units.get(name).cloned().or_else(|| {
|
||||
if name.ends_with("s") {
|
||||
if let Some(v) = self.lookup(&name[0..name.len()-1]) {
|
||||
return Some(v)
|
||||
if let Some(v) = self.units.get(name).cloned() {
|
||||
return Some(v)
|
||||
}
|
||||
for (unit, alias) in &self.aliases {
|
||||
if name == alias {
|
||||
return Some(Number(Number::one().0, unit.clone()))
|
||||
}
|
||||
}
|
||||
if name.ends_with("s") {
|
||||
if let Some(v) = self.lookup(&name[0..name.len()-1]) {
|
||||
return Some(v)
|
||||
}
|
||||
}
|
||||
for &(ref pre, ref value) in &self.prefixes {
|
||||
if name.starts_with(pre) {
|
||||
if let Some(v) = self.lookup(&name[pre.len()..]) {
|
||||
return Some((&v * &value).unwrap())
|
||||
}
|
||||
}
|
||||
for &(ref pre, ref value) in &self.prefixes {
|
||||
if name.starts_with(pre) {
|
||||
if let Some(v) = self.lookup(&name[pre.len()..]) {
|
||||
return Some((&v * &value).unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unit, alias) in &self.aliases {
|
||||
if name == alias {
|
||||
return Some(Number(Number::one().0, unit.clone()))
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Describes a value's unit, gives true if the unit is reciprocal
|
||||
|
@ -621,6 +622,7 @@ impl Context {
|
|||
enum Name {
|
||||
Unit(Rc<String>),
|
||||
Prefix(Rc<String>),
|
||||
Quantity(Rc<String>),
|
||||
}
|
||||
|
||||
struct Resolver {
|
||||
|
@ -653,6 +655,11 @@ impl Context {
|
|||
self.visit(&unit);
|
||||
return Some(())
|
||||
}
|
||||
let unit = Name::Quantity(name.clone());
|
||||
if self.input.get(&unit).is_some() {
|
||||
self.visit(&unit);
|
||||
return Some(())
|
||||
}
|
||||
if name.ends_with("s") {
|
||||
let v = Rc::new(name[0..name.len()-1].to_owned());
|
||||
if let Some(()) = self.lookup(&v) {
|
||||
|
@ -710,7 +717,8 @@ impl Context {
|
|||
self.temp_marks.insert(name.clone());
|
||||
if let Some(v) = self.input.get(name).cloned() {
|
||||
match *v {
|
||||
Def::Prefix(ref e) | Def::SPrefix(ref e) | Def::Unit(ref e) =>
|
||||
Def::Prefix(ref e) | Def::SPrefix(ref e) | Def::Unit(ref e) |
|
||||
Def::Quantity(ref e) =>
|
||||
self.eval(e),
|
||||
_ => (),
|
||||
}
|
||||
|
@ -733,6 +741,7 @@ impl Context {
|
|||
let name = resolver.intern(&name);
|
||||
let unit = match *def {
|
||||
Def::Prefix(_) | Def::SPrefix(_) => Name::Prefix(name),
|
||||
Def::Quantity(_) => Name::Quantity(name),
|
||||
_ => Name::Unit(name)
|
||||
};
|
||||
resolver.input.insert(unit.clone(), def);
|
||||
|
@ -754,6 +763,7 @@ impl Context {
|
|||
let name = match name {
|
||||
Name::Unit(name) => (*name).clone(),
|
||||
Name::Prefix(name) => (*name).clone(),
|
||||
Name::Quantity(name) => (*name).clone(),
|
||||
};
|
||||
match *def {
|
||||
Def::Dimension(ref dname) => {
|
||||
|
@ -785,21 +795,19 @@ impl Context {
|
|||
Ok(_) => println!("Prefix {} is not a number", name),
|
||||
Err(e) => println!("Prefix {} is malformed: {}", name, e)
|
||||
},
|
||||
Def::Quantity(ref expr) => match ctx.eval(expr) {
|
||||
Ok(Value::Number(v)) => {
|
||||
println!("Added {}", name);
|
||||
ctx.aliases.insert(v.1, name.clone());
|
||||
},
|
||||
Ok(_) => println!("Quantity {} is not a number", name),
|
||||
Err(e) => println!("Quantity {} is malformed: {}", name, e)
|
||||
},
|
||||
Def::DatePattern(ref pat) => ctx.datepatterns.push(pat.clone()),
|
||||
Def::Error(ref err) => println!("Def {}: {}", name, err),
|
||||
};
|
||||
}
|
||||
|
||||
for (expr, name) in defs.aliases {
|
||||
match ctx.eval(&expr) {
|
||||
Ok(Value::Number(v)) => {
|
||||
ctx.aliases.insert(v.1, name);
|
||||
},
|
||||
Ok(_) => println!("Alias {} is not a number", name),
|
||||
Err(e) => println!("Alias {}: {}", name, e)
|
||||
}
|
||||
}
|
||||
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ pub enum Token {
|
|||
Plus,
|
||||
Dash,
|
||||
Asterisk,
|
||||
Question,
|
||||
Error(String),
|
||||
}
|
||||
|
||||
|
@ -58,6 +59,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||
'-' => Token::Dash,
|
||||
'+' => Token::Plus,
|
||||
'*' => Token::Asterisk,
|
||||
'?' => Token::Question,
|
||||
'\\' => match self.0.next() {
|
||||
Some('\n') => self.next().unwrap(),
|
||||
Some(x) => Token::Error(format!("Invalid escape: \\{}", x)),
|
||||
|
@ -244,16 +246,8 @@ pub fn parse_expr(mut iter: &mut Iter) -> Expr {
|
|||
parse_add(iter)
|
||||
}
|
||||
|
||||
fn is_uppercase(name: &str) -> bool {
|
||||
name.len() > 1 && name.find(|c| match c {
|
||||
'A'...'Z' | '_' => false,
|
||||
_ => true
|
||||
}).is_none()
|
||||
}
|
||||
|
||||
pub fn parse(mut iter: &mut Iter) -> Defs {
|
||||
let mut map = vec![];
|
||||
let mut aliases = vec![];
|
||||
let mut line = 1;
|
||||
loop {
|
||||
match iter.next().unwrap() {
|
||||
|
@ -266,13 +260,6 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
|
|||
}
|
||||
},
|
||||
Token::Ident(name) => {
|
||||
if is_uppercase(&*name) {
|
||||
// alias
|
||||
let mut copy = iter.clone();
|
||||
let expr = parse_expr(&mut copy);
|
||||
aliases.push((expr, name.to_lowercase()));
|
||||
}
|
||||
|
||||
if name.ends_with("-") {
|
||||
// prefix
|
||||
let expr = parse_expr(iter);
|
||||
|
@ -297,6 +284,11 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
|
|||
} else {
|
||||
map.push((name.clone(), Rc::new(Def::Dimension(name))));
|
||||
}
|
||||
} else if let Some(&Token::Question) = iter.peek() {
|
||||
// quantity
|
||||
iter.next();
|
||||
let expr = parse_expr(iter);
|
||||
map.push((name, Rc::new(Def::Quantity(expr))));
|
||||
} else {
|
||||
// derived
|
||||
let expr = parse_expr(iter);
|
||||
|
@ -309,7 +301,6 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
|
|||
}
|
||||
Defs {
|
||||
defs: map,
|
||||
aliases: aliases,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -523,12 +523,11 @@ fn parse_datepattern(mut iter: &mut Iter) -> Vec<DatePattern> {
|
|||
|
||||
pub fn parse(mut iter: &mut Iter) -> Defs {
|
||||
let mut map = vec![];
|
||||
let mut aliases = vec![];
|
||||
let mut line = 1;
|
||||
loop {
|
||||
let mut copy = iter.clone();
|
||||
if let Some(a) = parse_alias(&mut copy) {
|
||||
aliases.push(a);
|
||||
map.push((a.1, Rc::new(Def::Quantity(a.0))));
|
||||
*iter = copy;
|
||||
continue
|
||||
}
|
||||
|
@ -588,7 +587,6 @@ pub fn parse(mut iter: &mut Iter) -> Defs {
|
|||
}
|
||||
Defs {
|
||||
defs: map,
|
||||
aliases: aliases,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue