1#![allow(deprecated)]
2use crate::charbool::*;
24use crate::combi::*;
25use crate::err::*;
26use crate::iter::*;
27use crate::parser::*;
28use crate::reader::*;
29use crate::strung::*;
30use crate::select::*;
33use std::convert::TryFrom;
34
35parser! { "Escapes a '\' and converts '\\n' '\\t' '\\r'"
36 (Esc->char)
37 last('\\',or!('t'.map(|_|'\t'), 'r'.map(|_|'\r'), 'n'.map(|_|'\n'), Any.one()))
38}
39
40parser! { "A string surrounded in Quotes"
41 (Quoted->String),
42 ('"',chars_until(or(Esc, Any.one()), '"')).map(|(_,( b,_))| b),
43}
44
45parser! { "A letter followed by numbers and letters or '_'"
46 (Ident->String)
47 string((Alpha.iplus(), (Alpha, NumDigit, '_').istar()))
48}
49
50#[deprecated(since = "0.5.0", note = "use Ident instead")]
51pub fn common_ident<'a>(it: &PIter<'a>) -> ParseRes<'a, String> {
52 Ident.parse(it)
53}
54
55parser! { "a usize"
56 (UInt->usize)
57 common_uint
58}
59
60#[deprecated(since = "0.5.1", note = " will go private as UInt does the job")]
61pub fn common_uint<'a>(it: &PIter<'a>) -> ParseRes<'a, usize> {
62 let mut added = false;
63 let mut res: usize = 0;
64 let mut it = it.clone();
65 loop {
66 let it2 = it.clone();
67 match it.next() {
68 Some(v) if is_num(v) => {
69 added = true;
70 res = res
71 .checked_mul(10)
72 .ok_or(it.err_s("A Smaller number"))?
73 .checked_add(v as usize - '0' as usize)
74 .ok_or(it.err_s("A Smaller number"))?;
75 }
76 Some('_') => {}
77 _ => {
78 if added {
79 return Ok((it2, res, None));
80 }
81 return it2.err_rs("[0-9]*");
82 }
83 }
84 }
85}
86
87parser! { "Returns a parsed isize"
88 (Int->isize)
89 (maybe('-'),UInt).try_map(|(m,n)|{
90 let n = isize::try_from(n).map_err(|_|Expected::Str("Int too big"))?;
91 match m {
92 Some(_)=>Ok(-n),
93 None=>Ok(n),
94 }
95 })
96}
97
98parser! { "the words 'true' or 'false'"
99 (Bool->bool)
100 or(keyword("true").map(|_|true),keyword("false").map(|_|false))
101}
102
103fn dot_part<'a>(i: &PIter<'a>) -> ParseRes<'a, f64> {
104 let mut res = 0.;
105 let mut exp = 0.1;
106 let mut it = i.clone();
107 if it.next() != Some('.') {
108 return i.err_rs("A Dot");
109 }
110 loop {
111 let it2 = it.clone();
112 match it.next() {
113 Some('_') => {}
114 Some(v) if is_num(v) => {
115 res += (((v as i64) as f64) - 48.0) * exp;
116 exp *= 0.1;
117 }
118 _ => return Ok((it2, res, None)),
119 }
120 }
121}
122
123parser! {"'e' followed by a uint, allowed on floats"
124 (Exponent->isize)
125 last('e',Int)
126}
127
128parser! { "floating point numbers eg '134.4e6'"
129 (Float->f64)
130 (Int,dot_part,maybe(Exponent)).map(|(n,d,e)|{
131 let mut res =n as f64;
132 res += res.signum() * d;
133 if let Some(exp) = e{
134 match exp >= 0{
135 true =>{
136 for _ in 0..exp {
137 res *= 10.
138 }
139 }
140 false =>{
141 for _ in 0..-exp {
142 res /= 10.
143 }
144 }
145 }
146 };
147 res
148 })
149
150}
151
152#[cfg(test)]
153pub mod test {
154 use super::*;
155 #[test]
156 pub fn test_parse_numbers() {
157 let r = Int.parse_s("32").unwrap();
158 assert_eq!(r, 32);
159 let r = Int.parse_s("-45023").unwrap();
160 assert_eq!(r, -45023);
161 let r = Int.parse_s("34_234").unwrap();
162 assert_eq!(r, 34234);
163 assert!(Int.parse_s("45654323456765432345676543212345654").is_err());
164 assert!(Int.parse_s(" 45").is_err());
165 }
166
167 #[test]
168 pub fn parse_floats() {
169 let r = Float.parse_s("32.").unwrap();
170 assert_eq!(r, 32.);
171 let r = Float.parse_s("-23.4").unwrap();
172 assert_eq!(r, -23.4);
173 let r = Float.parse_s("-23.4e2").unwrap();
174 assert_eq!(r, -2340.);
175 let r = Float.parse_s("123.4e-2").unwrap();
176 assert_eq!(r, 1.234);
177 assert!(Float.parse_s("123").is_err());
178 }
179}