microcad_lang/parse/
literal.rs1use microcad_core::Integer;
5
6use crate::{parse::*, parser::*, syntax::*};
7
8impl Parse for Refer<Integer> {
9 fn parse(pair: Pair) -> ParseResult<Self> {
10 match pair.as_str().parse::<i64>() {
11 Ok(value) => Ok(Refer::new(value, pair.into())),
12 Err(err) => Err(ParseError::ParseIntError(Refer::new(err, pair.into()))),
13 }
14 }
15}
16
17impl Parse for Literal {
18 fn parse(pair: Pair) -> ParseResult<Self> {
19 Parser::ensure_rule(&pair, Rule::literal);
20
21 let inner = pair.inner().next().expect(INTERNAL_PARSE_ERROR);
22
23 let s = match inner.as_rule() {
24 Rule::number_literal => Literal::Number(NumberLiteral::parse(inner)?),
25 Rule::integer_literal => Literal::Integer(Refer::<Integer>::parse(inner)?),
26 Rule::bool_literal => match inner.as_str() {
27 "true" => Literal::Bool(Refer::new(true, pair.into())),
28 "false" => Literal::Bool(Refer::new(false, pair.into())),
29 _ => unreachable!(),
30 },
31 _ => unreachable!(),
32 };
33
34 Ok(s)
35 }
36}
37
38impl std::str::FromStr for Literal {
39 type Err = ParseError;
40
41 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
42 Parser::parse_rule::<Self>(Rule::literal, s, 0)
43 }
44}
45
46impl Parse for NumberLiteral {
47 fn parse(pair: Pair) -> ParseResult<Self> {
48 Parser::ensure_rule(&pair, Rule::number_literal);
49
50 let mut inner = pair.inner();
51 let number_token = inner.next().expect("Expected number token");
52
53 assert!(
54 number_token.as_rule() == Rule::number
55 || number_token.as_rule() == Rule::integer_literal
56 );
57
58 let value = match number_token.as_str().parse::<f64>() {
59 Ok(value) => value,
60 Err(err) => return Err(ParseError::ParseFloatError(Refer::new(err, pair.src_ref()))),
61 };
62
63 let mut unit = Unit::None;
64
65 if let Some(unit_token) = inner.next() {
66 unit = Unit::parse(unit_token)?;
67 }
68 Ok(NumberLiteral(value, unit, pair.clone().into()))
69 }
70}
71
72impl std::str::FromStr for NumberLiteral {
73 type Err = ParseError;
74
75 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
76 Parser::parse_rule(Rule::number_literal, s, 0)
77 }
78}
79
80impl Parse for Unit {
81 fn parse(pair: Pair) -> ParseResult<Self> {
82 use std::str::FromStr;
83 match Unit::from_str(pair.as_str()) {
84 Ok(unit) => Ok(unit),
85 Err(()) => Err(ParseError::UnknownUnit(Refer::new(
86 pair.as_str().to_string(),
87 pair.into(),
88 ))),
89 }
90 }
91}
92
93impl std::str::FromStr for Unit {
94 type Err = ();
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 match s {
97 "" => Ok(Self::None),
99 "%" => Ok(Self::Percent),
100
101 "m" => Ok(Self::Meter),
103 "cm" => Ok(Self::Centimeter),
104 "mm" => Ok(Self::Millimeter),
105 "µm" => Ok(Self::Micrometer),
106 "in" => Ok(Self::Inch),
107 "\"" => Ok(Self::Inch),
108 "ft" => Ok(Self::Foot),
109 "\'" => Ok(Self::Foot),
110 "yd" => Ok(Self::Yard),
111
112 "deg" => Ok(Self::Deg),
114 "°" => Ok(Self::DegS),
115 "grad" => Ok(Self::Grad),
116 "turns" => Ok(Self::Turns),
117 "rad" => Ok(Self::Rad),
118
119 "g" => Ok(Self::Gram),
121 "kg" => Ok(Self::Kilogram),
122 "lb" => Ok(Self::Pound),
123 "oz" => Ok(Self::Ounce),
124
125 "m²" | "m2" => Ok(Self::Meter2),
127 "cm²" | "cm2" => Ok(Self::Centimeter2),
128 "mm²" | "mm2" => Ok(Self::Millimeter2),
129 "µm²" | "µm2" => Ok(Self::Micrometer2),
130 "in²" | "in2" => Ok(Self::Inch2),
131 "ft²" | "ft2" => Ok(Self::Foot2),
132 "yd²" | "yd2" => Ok(Self::Yard2),
133
134 "m³" | "m3" => Ok(Self::Meter3),
136 "cm³" | "cm3" => Ok(Self::Centimeter3),
137 "mm³" | "mm3" => Ok(Self::Millimeter3),
138 "µm³" | "µm3" => Ok(Self::Micrometer3),
139 "in³" | "in3" => Ok(Self::Inch3),
140 "ft³" | "ft3" => Ok(Self::Foot3),
141 "yd³" | "yd3" => Ok(Self::Yard3),
142 "ml" => Ok(Self::Milliliter),
143 "cl" => Ok(Self::Centiliter),
144 "l" => Ok(Self::Liter),
145 "µl" => Ok(Self::Microliter),
146
147 "g/mm³" => Ok(Self::GramPerMillimeter3),
148 "g/m³" => Ok(Self::GramPerMeter3),
149
150 _ => Err(()),
152 }
153 }
154}