1#![allow(clippy::collapsible_if)]
4
5use std::str::FromStr;
23use crate::vval::{VVal};
24use crate::vval::Syntax;
25
26pub mod state;
27
28pub use state::State;
29pub use state::{ParseValueError, ParseNumberError, ParseError, ParseErrorKind};
30use state::StrPart;
31
32fn add_c_to_vec(v: &mut Vec<u8>, c: char) {
34 if c.is_ascii() {
35 v.push((c as u32) as u8);
36 } else {
37 let mut b = [0; 4];
38 for cb in c.encode_utf8(&mut b).as_bytes().iter() {
39 v.push(*cb);
40 }
41 }
42}
43
44fn addchr(v: &mut Vec<u8>, s: &mut String, b: bool, c: char) {
47 if b { add_c_to_vec(v, c); }
48 else { s.push(c); }
49}
50
51fn parse_q_string(ps: &mut State, bytes: bool) -> Result<VVal, ParseError> {
53 let vec = ps.syn(Syntax::Str);
54
55 if bytes {
56 vec.push(VVal::new_byt(
57 parse_quoted(ps, Vec::new(), add_c_to_vec)?));
58 } else {
59 vec.push(VVal::new_str_mv(
60 parse_quoted(ps, String::new(), |v, c| v.push(c))?));
61 }
62
63 Ok(vec)
64}
65
66fn parse_quoted<F, V>(ps: &mut State, mut v: V, add_char: F) -> Result<V, ParseError>
68 where F: Fn(&mut V, char)
69{
70 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("string"))); }
71
72 let quote_char = ps.expect_some(ps.peek())?;
73 ps.consume();
74
75 let quote_char = match quote_char {
76 '[' => ']',
77 '(' => ')',
78 '{' => '}',
79 '<' => '>',
80 _ => quote_char
81 };
82
83 while ps.peek().unwrap_or(quote_char) != quote_char {
84 let c = ps.expect_some(ps.peek())?;
85 ps.consume();
86 add_char(&mut v, c);
87 }
88
89 if !ps.consume_if_eq(quote_char) {
90 return Err(ps.err(
91 ParseErrorKind::ExpectedToken(quote_char, "quote string end")));
92 }
93
94 ps.skip_ws_and_comments();
95
96 Ok(v)
97}
98
99enum NVecKind {
100 Int,
101 Flt,
102}
103
104fn parse_nvec_body(ps: &mut State, kind: NVecKind) -> Result<VVal, ParseError> {
107 match ps.expect_some(ps.peek())? {
108 '(' => {
109 ps.consume_wsc();
110 let vec = ps.syn(match kind {
111 NVecKind::Int => Syntax::IVec,
112 NVecKind::Flt => Syntax::FVec,
113 });
114
115 vec.push(parse_expr(ps)?);
116 while ps.consume_if_eq_wsc(',') {
117 vec.push(parse_expr(ps)?);
118 }
119
120 let dim = vec.len() - 1;
122
123 if !ps.consume_if_eq_wsc(')') {
124 Err(ps.err(ParseErrorKind::ExpectedToken(')', "numerical vector end")))
125 } else if !(1..=4).contains(&dim) {
126 Err(ps.err(ParseValueError::VectorLength))
127 } else {
128 Ok(vec)
129 }
130 },
131 _ => Err(ps.err(ParseErrorKind::ExpectedToken('(', "numerical vector start"))),
132 }
133}
134
135pub fn parse_2hex(ps: &mut State) -> Result<u8, ParseError> {
136 let hex = ps.peek2();
137 if let Some(h) = hex {
138 let h = h.to_string();
139 ps.consume();
140 ps.consume();
141 if let Ok(cn) = u8::from_str_radix(&h, 16) {
142 Ok(cn)
143 } else {
144 Err(ps.err(ParseErrorKind::BadEscape("Bad hex escape in string")))
145 }
146 } else {
147 Err(ps.err(ParseErrorKind::EOF("string hex escape")))
148 }
149}
150
151pub fn parse_unicode_hex(ps: &mut State) -> Result<char, ParseError> {
152 if !ps.consume_if_eq('{') {
153 return Err(ps.err(ParseErrorKind::ExpectedToken('{', "unicode escape start")));
154 }
155
156 let uh = ps.take_while(|c| c.is_digit(16));
157
158 let c =
159 if let Ok(cn) = u32::from_str_radix(&uh.to_string(), 16) {
160 if let Some(c) = std::char::from_u32(cn) {
161 c
162 } else {
163 return Err(ps.err(ParseErrorKind::BadEscape(
164 "Bad char in unicode escape in string"
165 )));
166 }
167 } else {
168 return Err(ps.err(ParseErrorKind::BadEscape(
169 "Bad unicode hex escape in string"
170 )));
171 };
172
173 if !ps.consume_if_eq('}') {
174 return Err(ps.err(ParseErrorKind::ExpectedToken('}', "unicode escape end")));
175 }
176
177 Ok(c)
178}
179
180#[derive(Debug, Clone, Copy)]
181pub enum EscSeqValue {
182 Char(char),
183 Byte(u8),
184}
185
186pub fn parse_ascii_char_name(ps: &mut State) -> Result<EscSeqValue, ParseError> {
187 if ps.consume_lookahead("NULL") || ps.consume_lookahead("null") {
188 Ok(EscSeqValue::Byte(b'\x00'))
189 } else if ps.consume_lookahead("SOH") || ps.consume_lookahead("soh") {
190 Ok(EscSeqValue::Byte(b'\x01'))
191 } else if ps.consume_lookahead("STX") || ps.consume_lookahead("stx") {
192 Ok(EscSeqValue::Byte(b'\x02'))
193 } else if ps.consume_lookahead("ETX") || ps.consume_lookahead("etx") {
194 Ok(EscSeqValue::Byte(b'\x03'))
195 } else if ps.consume_lookahead("EOT") || ps.consume_lookahead("eot") {
196 Ok(EscSeqValue::Byte(b'\x04'))
197 } else if ps.consume_lookahead("ENQ") || ps.consume_lookahead("enq") {
198 Ok(EscSeqValue::Byte(b'\x05'))
199 } else if ps.consume_lookahead("ACK") || ps.consume_lookahead("ack") {
200 Ok(EscSeqValue::Byte(b'\x06'))
201 } else if ps.consume_lookahead("BEL") || ps.consume_lookahead("bel") {
202 Ok(EscSeqValue::Byte(b'\x07'))
203 } else if ps.consume_lookahead("BS") || ps.consume_lookahead("bs") {
204 Ok(EscSeqValue::Byte(b'\x08'))
205 } else if ps.consume_lookahead("HT") || ps.consume_lookahead("ht") {
206 Ok(EscSeqValue::Byte(b'\x09'))
207 } else if ps.consume_lookahead("LF") || ps.consume_lookahead("lf") {
208 Ok(EscSeqValue::Byte(b'\x0a'))
209 } else if ps.consume_lookahead("VT") || ps.consume_lookahead("vt") {
210 Ok(EscSeqValue::Byte(b'\x0b'))
211 } else if ps.consume_lookahead("FF") || ps.consume_lookahead("ff") {
212 Ok(EscSeqValue::Byte(b'\x0c'))
213 } else if ps.consume_lookahead("CR") || ps.consume_lookahead("cr") {
214 Ok(EscSeqValue::Byte(b'\x0d'))
215 } else if ps.consume_lookahead("SO") || ps.consume_lookahead("so") {
216 Ok(EscSeqValue::Byte(b'\x0e'))
217 } else if ps.consume_lookahead("SI") || ps.consume_lookahead("si") {
218 Ok(EscSeqValue::Byte(b'\x0f'))
219 } else if ps.consume_lookahead("DLE") || ps.consume_lookahead("dle") {
220 Ok(EscSeqValue::Byte(b'\x10'))
221 } else if ps.consume_lookahead("DC1") || ps.consume_lookahead("dc1") {
222 Ok(EscSeqValue::Byte(b'\x11'))
223 } else if ps.consume_lookahead("DC2") || ps.consume_lookahead("dc2") {
224 Ok(EscSeqValue::Byte(b'\x12'))
225 } else if ps.consume_lookahead("DC3") || ps.consume_lookahead("dc3") {
226 Ok(EscSeqValue::Byte(b'\x13'))
227 } else if ps.consume_lookahead("DC4") || ps.consume_lookahead("dc4") {
228 Ok(EscSeqValue::Byte(b'\x14'))
229 } else if ps.consume_lookahead("NAK") || ps.consume_lookahead("nak") {
230 Ok(EscSeqValue::Byte(b'\x15'))
231 } else if ps.consume_lookahead("SYN") || ps.consume_lookahead("syn") {
232 Ok(EscSeqValue::Byte(b'\x16'))
233 } else if ps.consume_lookahead("ETB") || ps.consume_lookahead("etb") {
234 Ok(EscSeqValue::Byte(b'\x17'))
235 } else if ps.consume_lookahead("CAN") || ps.consume_lookahead("can") {
236 Ok(EscSeqValue::Byte(b'\x18'))
237 } else if ps.consume_lookahead("EM") || ps.consume_lookahead("em") {
238 Ok(EscSeqValue::Byte(b'\x19'))
239 } else if ps.consume_lookahead("SUB") || ps.consume_lookahead("sub") {
240 Ok(EscSeqValue::Byte(b'\x1a'))
241 } else if ps.consume_lookahead("ESC") || ps.consume_lookahead("esc") {
242 Ok(EscSeqValue::Byte(b'\x1b'))
243 } else if ps.consume_lookahead("FS") || ps.consume_lookahead("fs") {
244 Ok(EscSeqValue::Byte(b'\x1c'))
245 } else if ps.consume_lookahead("GS") || ps.consume_lookahead("gs") {
246 Ok(EscSeqValue::Byte(b'\x1d'))
247 } else if ps.consume_lookahead("RS") || ps.consume_lookahead("rs") {
248 Ok(EscSeqValue::Byte(b'\x1e'))
249 } else if ps.consume_lookahead("US") || ps.consume_lookahead("us") {
250 Ok(EscSeqValue::Byte(b'\x1f'))
251 } else if ps.consume_lookahead("DEL") || ps.consume_lookahead("del") {
252 Ok(EscSeqValue::Byte(b'\x7f'))
253 } else if ps.consume_lookahead("SPACE")|| ps.consume_lookahead("space") {
254 Ok(EscSeqValue::Byte(b'\x20'))
255 } else if ps.consume_lookahead("NBSP")|| ps.consume_lookahead("nbsp") {
256 Ok(EscSeqValue::Byte(b'\xff'))
257 } else {
258 Err(ps.err(ParseErrorKind::BadEscape("Bad ascii character name escape")))
259 }
260}
261
262pub fn parse_str_backslash(ps: &mut State) -> Result<EscSeqValue, ParseError>
263{
264 match ps.expect_some(ps.peek())? {
265 'n' => { ps.consume(); Ok(EscSeqValue::Char('\n')) },
266 'r' => { ps.consume(); Ok(EscSeqValue::Char('\r')) },
267 't' => { ps.consume(); Ok(EscSeqValue::Char('\t')) },
268 '0' => { ps.consume(); Ok(EscSeqValue::Char('\0')) },
269 'x' => { ps.consume(); Ok(EscSeqValue::Byte(parse_2hex(ps)?)) },
270 'u' => { ps.consume(); Ok(EscSeqValue::Char(parse_unicode_hex(ps)?)) },
271 '<' => { ps.consume();
272 let ret = parse_ascii_char_name(ps);
273 if !ps.consume_if_eq('>') {
274 return Err(ps.err(ParseErrorKind::BadEscape(
275 "Bad ascii character name escape, does not end with '>'")));
276 }
277 ret
278 },
279 c => { ps.consume(); Ok(EscSeqValue::Char(c)) },
280 }
281}
282
283fn parse_char(ps: &mut State, byte: bool) -> Result<VVal, ParseError> {
285 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("character"))); }
286
287 if !ps.consume_if_eq('\'') {
288 return Err(ps.err(ParseErrorKind::ExpectedToken('\'', "character start")));
289 }
290
291 let c = ps.expect_some(ps.peek())?;
292 let ret =
293 match c {
294 '\\' => {
295 ps.consume();
296 match parse_str_backslash(ps)? {
297 EscSeqValue::Char(c) => {
298 if byte {
299 let c = c as u32;
300 if c > 0xFF {
301 VVal::new_byte('?' as u32 as u8)
302 } else {
303 VVal::new_byte(c as u8)
304 }
305 } else {
306 VVal::new_char(c)
307 }
308 },
309 EscSeqValue::Byte(b) =>
310 if byte { VVal::new_byte(b) }
311 else { VVal::new_char(b as char) },
312 }
313 },
314 _ => {
315 ps.consume();
316 if byte {
317 let c = c as u32;
318 if c > 0xFF {
319 VVal::new_byte('?' as u32 as u8)
320 } else {
321 VVal::new_byte(c as u8)
322 }
323 } else {
324 VVal::new_char(c)
325 }
326 },
327 };
328
329 if !ps.consume_if_eq('\'') {
330 return Err(ps.err(ParseErrorKind::ExpectedToken('\'', "character end")));
331 }
332
333 ps.skip_ws_and_comments();
334
335 Ok(ret)
336}
337
338fn parse_string(ps: &mut State, bytes: bool) -> Result<VVal, ParseError> {
340 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("string"))); }
341
342 if !ps.consume_if_eq('"') {
343 return Err(ps.err(ParseErrorKind::ExpectedToken('\"', "string start")));
344 }
345
346 let vec = ps.syn(Syntax::Str);
347
348 let mut s = String::from("");
349 let mut v : Vec<u8> = Vec::new();
350
351 while ps.peek().unwrap_or('"') != '"' {
352 let c = ps.expect_some(ps.peek())?;
353 match c {
354 '\\' => {
355 ps.consume();
356 match parse_str_backslash(ps)? {
357 EscSeqValue::Char(c) => addchr(&mut v, &mut s, bytes, c),
358 EscSeqValue::Byte(b) =>
359 if bytes { v.push(b); }
360 else { s.push(b as char); },
361 }
362 },
363 _ => { ps.consume(); addchr(&mut v, &mut s, bytes, c); },
364 }
365 }
366
367 if bytes {
368 vec.push(VVal::new_byt(v));
369 } else {
370 vec.push(VVal::new_str(&s));
371 }
372
373 if !ps.consume_if_eq('"') {
374 return Err(ps.err(ParseErrorKind::ExpectedToken('\"', "string end")));
375 }
376
377 ps.skip_ws_and_comments();
378
379 Ok(vec)
380}
381
382#[allow(clippy::collapsible_else_if)]
383#[allow(clippy::cast_lossless)]
384fn parse_num(ps: &mut State) -> Result<VVal, ParseError> {
385 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("number"))); }
386
387 let c = ps.expect_some(ps.peek())?;
388 let sign = match c {
389 '-' => {
390 ps.consume();
391 if !ps.peek().unwrap_or(' ').is_digit(10) {
392 ps.skip_ws_and_comments();
393 return Ok(make_var(ps, "-"));
394 }
395 -1
396 },
397 '+' => {
398 ps.consume();
399 if !ps.peek().unwrap_or(' ').is_digit(10) {
400 ps.skip_ws_and_comments();
401 return Ok(make_var(ps, "+"));
402 }
403 1
404 },
405 _ => 1
406 };
407
408 let radix_or_num = ps.take_while(|c| c.is_digit(10)).to_string();
409
410 let (radix, num) = if ps.consume_if_eq('r') {
411 let radix = radix_or_num.parse::<u8>().unwrap_or(10);
412 if !(2..=36).contains(&radix) {
413 return Err(ps.err(ParseNumberError::UnsupportedRadix(radix)));
414 }
415
416 (radix, ps.take_while(|c| c.is_digit(radix as u32)).to_string())
417 } else if ps.consume_if_eq('x') {
418 if radix_or_num != "0" {
419 return Err(ps.err(ParseNumberError::UnsupportedRadixPrefix('x', radix_or_num)));
420 }
421 (16, ps.take_while(|c| c.is_digit(16)).to_string())
422 } else if ps.consume_if_eq('b') {
423 if radix_or_num != "0" {
424 return Err(ps.err(ParseNumberError::UnsupportedRadixPrefix('b', radix_or_num)));
425 }
426 (2, ps.take_while(|c| c.is_digit(2)).to_string())
427 } else if ps.consume_if_eq('o') {
428 if radix_or_num != "0" {
429 return Err(ps.err(ParseNumberError::UnsupportedRadixPrefix('o', radix_or_num)));
430 }
431 (8, ps.take_while(|c| c.is_digit(8)).to_string())
432 } else {
433 (10, radix_or_num)
434 };
435
436 let (is_float, fract_num) = if ps.consume_if_eq('.') {
437 let fract_digits = ps.take_while(|c| c.is_digit(radix as u32)).to_string();
438 if let Ok(fract_num) = u64::from_str_radix(&fract_digits, radix as u32) {
439 (true, (fract_num as f64) / (radix as f64).powf(fract_digits.len() as f64))
440 } else {
441 return Err(ps.err(ParseNumberError::InvalidFractionalDigits(fract_digits)));
442 }
443 } else {
444 (false, 0.0)
445 };
446
447 ps.skip_ws_and_comments();
448
449 match u64::from_str_radix(&num, radix as u32) {
450 Ok(num) => {
451 if is_float {
452 if sign == -1 {
453 Ok(VVal::Flt(-((num as f64) + fract_num)))
454 } else {
455 Ok(VVal::Flt((num as f64) + fract_num))
456 }
457 } else {
458 if sign == -1 {
459 Ok(VVal::Int((num as i64).wrapping_neg()))
460 } else {
461 Ok(VVal::Int(num as i64))
462 }
463 }
464 },
465 Err(e) => Err(ps.err(ParseNumberError::InvalidRadix(num, radix, e)))
466 }
467}
468
469fn parse_list(ps: &mut State) -> Result<VVal, ParseError> {
470 if !ps.consume_if_eq_wsc('[') {
471 return Err(ps.err(ParseErrorKind::ExpectedToken('[', "list start")));
472 }
473
474 let list = ps.syn(Syntax::Lst);
475
476 while ps.expect_some(ps.peek())? != ']' {
477 if ps.consume_if_eq_wsc('*') {
478 let r = ps.syn(Syntax::VecSplice);
479 r.push(parse_expr(ps)?);
480 list.push(r);
481 } else {
482 list.push(parse_expr(ps)?);
483 }
484 if !ps.consume_if_eq_wsc(',') { break; }
485 }
486
487 if !ps.consume_if_eq_wsc(']') {
488 return Err(ps.err(ParseErrorKind::ExpectedToken(']', "list end")));
489 }
490
491 Ok(list)
492}
493
494fn parse_map(ps: &mut State) -> Result<VVal, ParseError> {
495 if !ps.consume_if_eq_wsc('{') {
497 return Err(ps.err(ParseErrorKind::ExpectedToken('{', "map start")));
498 }
499
500 let map = ps.syn(Syntax::Map);
501
502 while ps.expect_some(ps.peek())? != '}' {
503 let c = ps.expect_some(ps.peek())?;
504
505 map.push(
506 if ps.consume_if_eq_wsc('*') {
507 let r = ps.syn(Syntax::MapSplice);
508 r.push(parse_expr(ps)?);
509 r
510
511 } else {
512 let key = if is_ident_start(c) {
513 VVal::new_sym_mv(parse_identifier(ps)?)
514 } else {
515 parse_expr(ps)?
516 };
517 if !ps.consume_if_eq_wsc('=') {
518 return Err(ps.err(ParseErrorKind::ExpectedToken('=', "map key")));
519 }
520
521 let elem = VVal::vec();
522 elem.push(key);
523 elem.push(parse_expr(ps)?);
524 elem
525 });
526
527 if !ps.consume_if_eq_wsc(',') { break; }
528 }
529
530 if !ps.consume_if_eq_wsc('}') {
531 return Err(ps.err(ParseErrorKind::ExpectedToken('}', "map end")));
532 }
533
534 Ok(map)
535}
536
537
538fn parse_special_value(ps: &mut State) -> Result<VVal, ParseError> {
539 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("literal value"))); }
540 let c = ps.expect_some(ps.peek())?;
541
542 match c {
543 'r' => {
544 ps.consume();
545 let mode =
546 if ps.consume_if_eq('g') { "g" }
547 else if ps.consume_if_eq('s') { "s" }
548 else { "f" };
549
550 let pattern_source = parse_quoted(ps, String::new(), |s, c| s.push(c))?;
551 let vec = ps.syn(Syntax::Pattern);
552 vec.push(VVal::new_str_mv(pattern_source));
553 vec.push(VVal::new_str_mv(String::from(mode)));
554 Ok(vec)
555 },
556 'S' => {
557 ps.consume();
558 let selector_source = parse_quoted(ps, String::new(), |s, c| s.push(c))?;
559 let vec = ps.syn(Syntax::Selector);
560 vec.push(VVal::new_str_mv(selector_source));
561 Ok(vec)
562 },
563 'M' => {
564 ps.consume_wsc();
565 let pat_expr = parse_expr(ps)?;
566 let vec = ps.syn(Syntax::StructPattern);
567 vec.push(pat_expr);
568 Ok(vec)
569 },
570 'F' => {
571 ps.consume_wsc();
572 let str_lit = parse_string_lit(ps)?;
573 let vec = ps.syn(Syntax::Formatter);
574 vec.push(str_lit);
575 Ok(vec)
576 },
577 '\\' => { ps.consume_wsc(); Ok(make_var(ps, "\\")) },
578 '[' => parse_list(ps),
579 '{' => parse_map(ps),
580 'n' => {
581 if ps.consume_lookahead("none") {
582 ps.skip_ws_and_comments();
583 } else {
584 ps.consume_wsc();
585 }
586 Ok(VVal::None)
587 },
588 'i' => {
589 if ps.consume_lookahead("iter") {
590 ps.skip_ws_and_comments();
591
592 let err = ps.syn(Syntax::Iter);
593 err.push(parse_expr(ps)?);
594 Ok(err)
595 } else {
596 ps.consume();
597 parse_nvec_body(ps, NVecKind::Int)
598 }
599 },
600 'D' if ps.consume_lookahead("DEBUG") => {
601 ps.skip_ws_and_comments();
602 Ok(ps.syn(Syntax::DebugPrint))
603 },
604 'd' => {
605 if ps.consume_lookahead("data") {
606 ps.skip_ws_and_comments();
607 } else {
608 ps.consume_wsc();
609 }
610 Ok(ps.syn(Syntax::SelfData))
611 },
612 's' => {
613 if ps.consume_lookahead("self") {
614 ps.skip_ws_and_comments();
615 } else {
616 ps.consume_wsc();
617 }
618 Ok(ps.syn(Syntax::SelfObj))
619 },
620 't' => {
621 if ps.consume_lookahead("true") {
622 ps.skip_ws_and_comments();
623 } else {
624 ps.consume_wsc();
625 }
626 Ok(VVal::Bol(true))
627 },
628 'f' => {
629 if ps.consume_lookahead("false") {
630 ps.skip_ws_and_comments();
631 Ok(VVal::Bol(false))
632 } else if ps.lookahead("f(") {
633 ps.consume();
634 parse_nvec_body(ps, NVecKind::Flt)
635 } else {
636 ps.consume_wsc();
637 Ok(VVal::Bol(false))
638 }
639 },
640 'e' => {
641 if ps.consume_lookahead("error") {
642 ps.skip_ws_and_comments();
643 } else {
644 ps.consume_wsc();
645 }
646
647 let err = ps.syn(Syntax::Err);
648 err.push(parse_expr(ps)?);
649 Ok(err)
650 },
651 '*' => {
652 ps.consume_wsc();
653 let r = ps.syn(Syntax::Deref);
654 r.push(parse_value(ps)?);
655 Ok(r)
656 },
657 'o' => {
658 ps.consume_wsc();
659 if !ps.consume_if_eq_wsc('(') {
660 return Err(ps.err(ParseErrorKind::ExpectedToken('(', "start of optional value")))
661 }
662
663 if ps.consume_if_eq_wsc(')') {
664 Ok(ps.syn(Syntax::Opt))
665 } else {
666 let a = parse_expr(ps)?;
667 let opt_v = ps.syn(Syntax::Opt);
668 opt_v.push(a);
669
670 if ps.consume_if_eq_wsc(')') {
671 Ok(opt_v)
672 } else {
673 Err(ps.err(ParseErrorKind::ExpectedToken(')', "end of optional value")))
674 }
675 }
676 },
677 'p' => {
678 ps.consume_wsc();
679 if !ps.consume_if_eq_wsc('(') {
680 return Err(ps.err(ParseErrorKind::ExpectedToken('(', "pair start")))
681 }
682 let a = parse_expr(ps)?;
683 let ret =
684 if ps.consume_if_eq_wsc(',') {
685 let b = parse_expr(ps)?;
686 VVal::pair(a, b)
687 } else {
688 VVal::pair(a, VVal::None)
689 };
690
691 if ps.consume_if_eq_wsc(')') {
692 Ok(ret)
693 } else {
694 Err(ps.err(ParseErrorKind::ExpectedToken(')', "pair end")))
695 }
696 },
697 ':' => {
698 ps.consume_wsc();
699 let capture = ps.syn(Syntax::CaptureRef);
700 capture.push(VVal::new_sym_mv(parse_identifier(ps)?));
701 Ok(capture)
702 },
703 'w' if ps.consume_lookahead("weak&")
704 || ps.consume_lookahead("w&") => {
705
706 ps.skip_ws_and_comments();
707 let r = ps.syn(Syntax::WRef);
708 r.push(parse_value(ps)?);
709 Ok(r)
710 },
711 '&' => {
712 if ps.consume_lookahead("&&") {
713 ps.skip_ws_and_comments();
714 let r = ps.syn(Syntax::Ref);
715 r.push(parse_value(ps)?);
716 Ok(r)
717 } else {
718 ps.consume_wsc();
719 let r = ps.syn(Syntax::HRef);
720 r.push(parse_value(ps)?);
721 Ok(r)
722 }
723 },
724 '%' => {
725 let mut sp = ps.syn_pos(Syntax::Block);
726
727 ps.consume();
728
729 if ps.consume_lookahead(":") {
730 let syntax_name = parse_identifier(ps)?;
731 if let Ok(syn) = Syntax::from_str(&syntax_name) {
732 ps.skip_ws_and_comments();
733 sp.syn = syn;
734 Ok(VVal::Syn(sp))
735
736 } else {
737 Err(ps.err(ParseValueError::Expected(
738 "valid WLambda syntax type identifier ($%:Block, $%:Call, ...)")))
739 }
740 } else {
741 Err(ps.err(ParseErrorKind::ExpectedToken(':', "syntax symbol start")))
742 }
743 },
744 '@' => {
745 let a = ps.syn(Syntax::Accum);
746 if ps.consume_lookahead("@int") || ps.consume_lookahead("@i") {
747 ps.skip_ws_and_comments();
748 a.push(VVal::new_sym("int"));
749 a.push(parse_expr(ps)?);
750 Ok(a)
751
752 } else if ps.consume_lookahead("@float") || ps.consume_lookahead("@f") {
753 ps.skip_ws_and_comments();
754 a.push(VVal::new_sym("float"));
755 a.push(parse_expr(ps)?);
756 Ok(a)
757
758 } else if ps.consume_lookahead("@string") || ps.consume_lookahead("@s") {
759 ps.skip_ws_and_comments();
760 a.push(VVal::new_sym("string"));
761 a.push(parse_expr(ps)?);
762 Ok(a)
763
764 } else if ps.consume_lookahead("@bytes") || ps.consume_lookahead("@b") {
765 ps.skip_ws_and_comments();
766 a.push(VVal::new_sym("bytes"));
767 a.push(parse_expr(ps)?);
768 Ok(a)
769
770 } else if ps.consume_lookahead("@vec") || ps.consume_lookahead("@v") {
771 ps.skip_ws_and_comments();
772 a.push(VVal::new_sym("vec"));
773 a.push(parse_expr(ps)?);
774 Ok(a)
775
776 } else if ps.consume_lookahead("@map") || ps.consume_lookahead("@m") {
777 ps.skip_ws_and_comments();
778 a.push(VVal::new_sym("map"));
779 a.push(parse_expr(ps)?);
780 Ok(a)
781
782 } else if ps.consume_lookahead("@@") {
783 ps.skip_ws_and_comments();
784 a.push(VVal::new_sym("@"));
785 Ok(a)
786
787 } else {
788 Err(ps.err(ParseValueError::ExpectedAccumulator))
789 }
790 },
791 '+' => {
792 ps.consume_wsc();
793 Ok(ps.syn(Syntax::Accum))
794 },
795 c => {
796 Err(ps.err(ParseValueError::UnknownSpecialIdentifier(c)))
797 }
798 }
799}
800
801#[allow(dead_code)]
802fn is_var(expr: &VVal) -> bool {
803 if let Some(VVal::Syn(s)) = expr.at(0) {
804 return s.syn() == Syntax::Var;
805 }
806 false
807}
808
809fn is_call(expr: &VVal) -> bool {
810 if let Some(VVal::Syn(s)) = expr.at(0) {
811 return s.syn() == Syntax::Call;
812 }
813 false
814}
815
816fn make_to_call(ps: &State, expr: VVal) -> VVal {
817 let call = ps.syn(Syntax::Call);
818 call.push(expr);
819 call
820}
821
822fn make_var(ps: &State, identifier: &str) -> VVal {
823 let id = ps.syn(Syntax::Var);
824 id.push(VVal::new_sym(identifier));
825 id
826}
827
828fn make_sym(ps: &State, identifier: &str) -> VVal {
829 let id = ps.syn(Syntax::Key);
830 id.push(VVal::new_sym(identifier));
831 id
832}
833
834fn make_binop(ps: &State, op: StrPart) -> VVal {
835 if op == "&and" {
836 ps.syn(Syntax::And)
837
838 } else if op == "&or" {
839 ps.syn(Syntax::Or)
840
841 } else if op == "//" {
842 ps.syn(Syntax::BinOpSomeOr)
843
844 } else if op == "/?" {
845 ps.syn(Syntax::BinOpExtSomeOr)
846
847 } else if op == "/$e" {
848 ps.syn(Syntax::BinOpErrOr)
849
850 } else if op == "/$o" {
851 ps.syn(Syntax::BinOpOptOr)
852
853 } else if op == "/$n" {
854 ps.syn(Syntax::BinOpNoneOr)
855
856 } else if op == "+" {
857 ps.syn(Syntax::BinOpAdd)
858
859 } else if op == "-" {
860 ps.syn(Syntax::BinOpSub)
861
862 } else if op == "*" {
863 ps.syn(Syntax::BinOpMul)
864
865 } else if op == "/" {
866 ps.syn(Syntax::BinOpDiv)
867
868 } else if op == "%" {
869 ps.syn(Syntax::BinOpMod)
870
871 } else if op == ">" {
872 ps.syn(Syntax::BinOpGt)
873
874 } else if op == "<" {
875 ps.syn(Syntax::BinOpLt)
876
877 } else if op == "<=" {
878 ps.syn(Syntax::BinOpLe)
879
880 } else if op == ">=" {
881 ps.syn(Syntax::BinOpGe)
882
883 } else if op == "==" {
884 ps.syn(Syntax::BinOpEq)
885
886 } else if op == "=>" {
887 ps.syn(Syntax::OpNewPair)
888
889 } else if op == "&>" {
890 ps.syn(Syntax::OpCallRwL)
891
892 } else if op == "<&" {
893 ps.syn(Syntax::OpCallLwR)
894
895 } else if op == "&@>" {
896 ps.syn(Syntax::OpCallApplyRwL)
897
898 } else if op == "<@&" {
899 ps.syn(Syntax::OpCallApplyLwR)
900
901 } else if op == "+>" {
902 ps.syn(Syntax::OpColAddR)
903
904 } else if op == "<+" {
905 ps.syn(Syntax::OpColAddL)
906
907 } else {
908 make_to_call(ps, make_var(ps, &op.to_string()))
909 }
910}
911
912fn parse_identifier(ps: &mut State) -> Result<String, ParseError> {
913 if ps.peek().is_none() {
914 return Err(ps.err(ParseErrorKind::EOF("identifier")));
915 }
916
917 if ps.peek().unwrap() == '`' {
918 let mut identifier = "".to_string();
919 ps.consume();
920 while ps.peek().unwrap_or('`') != '`' {
921 let c = ps.expect_some(ps.peek())?;
922 match c {
923 '\\' => {
924 ps.consume();
925 if let Some(c) = ps.peek() {
926 ps.consume();
927 identifier.push(c);
928 } else {
929 return Err(ps.err(ParseErrorKind::EOF("identifier escape")));
930 }
931 },
932 _ => {
933 ps.consume();
934 identifier.push(c);
935 },
936 }
937 }
938
939 if !ps.consume_if_eq('`') {
940 return Err(ps.err(ParseErrorKind::ExpectedToken('`', "quoted identifier end")));
941 }
942
943 ps.skip_ws_and_comments();
944
945 Ok(identifier)
946 } else {
947 let identifier =
948 ps.take_while_wsc(|c| {
949 match c {
950 '.' | ',' | ';' | '{' | '}'
951 | '[' | ']' | '(' | ')' | '~' | '|' | '='
952 => false,
953 _ => !c.is_whitespace()
954 }
955 });
956 Ok(identifier.to_string())
957 }
958}
959
960fn is_ident_start(c: char) -> bool {
961 c.is_alphabetic() || c == '_' || c == '@' || c == '`' || c == '?'
962}
963
964fn parse_string_lit(ps: &mut State) -> Result<VVal, ParseError> {
965 match ps.expect_some(ps.peek())? {
966 '"' => parse_string(ps, false),
967 '\'' => parse_char(ps, false),
968 '$' => { ps.consume();
969 match ps.expect_some(ps.peek())? {
970 'b' => { ps.consume();
971 if ps.lookahead("'") {
972 parse_char(ps, true)
973 } else {
974 parse_string(ps, true)
975 }
976 },
977 'q' => { ps.consume(); parse_q_string(ps, false) },
978 'Q' => { ps.consume(); parse_q_string(ps, true) },
979 'c' => {
980 if ps.consume_lookahead("code") {
981 ps.skip_ws_and_comments();
982 } else {
983 ps.consume_wsc();
984 }
985
986 let code =
987 if ps.consume_if_eq_wsc('{') {
988 let code_start_pos = ps.remember();
989 parse_block(ps, false, false, true)?;
990 let code_end_pos = ps.remember();
991 let code = ps.collect(code_start_pos, code_end_pos).to_string();
992
993 if !ps.consume_if_eq_wsc('}') {
994 return Err(ps.err(
995 ParseErrorKind::ExpectedToken(
996 '}', "block end")));
997 }
998
999 code
1000 } else {
1001 let code_start_pos = ps.remember();
1002 parse_expr(ps)?;
1003 let code_end_pos = ps.remember();
1004 ps.collect(code_start_pos, code_end_pos).to_string()
1005 };
1006
1007 let vec = ps.syn(Syntax::Str);
1008 vec.push(VVal::new_str_mv(code));
1009 Ok(vec)
1010 },
1011 _ => Err(ps.err(ParseValueError::Expected("literal string"))),
1012 }
1013 },
1014 _ => Err(ps.err(ParseValueError::Expected("literal string"))),
1015 }
1016}
1017
1018fn parse_value(ps: &mut State) -> Result<VVal, ParseError> {
1019 match ps.expect_some(ps.peek())? {
1021 '0' ..= '9' | '+' | '-' => parse_num(ps),
1022 _ if ps.lookahead("$q")
1023 || ps.lookahead("$Q")
1024 || ps.lookahead("$b")
1025 || ps.lookahead("$c")
1026 || ps.lookahead("'")
1027 || ps.lookahead("\"") => parse_string_lit(ps),
1028 '$' => { ps.consume_wsc(); parse_special_value(ps) },
1029 '(' => {
1030 ps.consume_wsc();
1031 let expr = parse_expr(ps)?;
1032 if !ps.consume_if_eq_wsc(')') {
1033 return Err(ps.err(
1034 ParseErrorKind::ExpectedToken(
1035 ')', "sub expression end")));
1036 }
1037 Ok(expr)
1038 },
1039 '{' => {
1040 let syn = ps.syn_raw(Syntax::Func);
1041 let block = parse_block(ps, true, true, true)?;
1042 block.set_at(0, syn);
1043 block.insert_at(1, VVal::None);
1044 Ok(block)
1045 },
1046 '\\' => {
1047 ps.consume_wsc();
1048
1049 if ps.consume_if_eq_wsc(':') {
1050 let syn = ps.syn_raw(Syntax::Func);
1051
1052 let block_name = parse_identifier(ps)?;
1053 ps.skip_ws_and_comments();
1054 let block = parse_block(ps, true, true, true)?;
1055
1056 block.set_at(0, syn);
1057 block.insert_at(1, VVal::new_sym_mv(block_name));
1058 Ok(block)
1059 } else {
1060 let block = ps.syn(Syntax::Func);
1061
1062 let arity =
1063 if ps.lookahead("|") { parse_arity(ps)? }
1064 else { VVal::None };
1065
1066 let next_stmt = parse_stmt(ps)?;
1067 block.push(VVal::None);
1068 block.push(arity);
1069 block.push(next_stmt);
1070 Ok(block)
1071 }
1072 },
1073 ':' => {
1074 ps.consume_wsc();
1075 if ps.lookahead("\"") {
1076 let s = parse_string(ps, false)?;
1077 s.at(1).unwrap().with_s_ref(|s: &str|
1078 Ok(make_sym(ps, s)))
1079 } else {
1080 let id = parse_identifier(ps)?;
1081 Ok(make_sym(ps, &id))
1082 }
1083 },
1084 c if is_ident_start(c) => {
1085 let id = parse_identifier(ps)?;
1086 Ok(make_var(ps, &id))
1087 },
1088 _ => {
1089 Err(ps.err(ParseValueError::Expected("literal value, sub \
1090 expression, block, key or identifier")))
1091 }
1092 }
1093}
1094
1095#[allow(clippy::collapsible_else_if)]
1096fn optimize_get_key(ps: &mut State, obj: VVal, value: VVal) -> VVal {
1097 let mut first_syn = obj.v_(0);
1098
1099 if first_syn.get_syn() == Syntax::GetIdx && value.is_int() {
1100 first_syn.set_syn(Syntax::GetIdx2);
1101 obj.set_at(0, first_syn);
1102 obj.push(value);
1103 obj
1104
1105 } else if first_syn.get_syn() == Syntax::GetIdx2 && value.is_int() {
1106 first_syn.set_syn(Syntax::GetIdx3);
1107 obj.set_at(0, first_syn);
1108 obj.push(value);
1109 obj
1110
1111 } else if first_syn.get_syn() == Syntax::GetSym && value.v_(0).get_syn() == Syntax::Key {
1112 first_syn.set_syn(Syntax::GetSym2);
1113 obj.set_at(0, first_syn);
1114 obj.push(value.v_(1));
1115 obj
1116
1117 } else if first_syn.get_syn() == Syntax::GetSym2 && value.v_(0).get_syn() == Syntax::Key {
1118 first_syn.set_syn(Syntax::GetSym3);
1119 obj.set_at(0, first_syn);
1120 obj.push(value.v_(1));
1121 obj
1122
1123 } else if first_syn.get_syn() == Syntax::GetSym && value.v_(0).get_syn() == Syntax::Str {
1124 first_syn.set_syn(Syntax::GetSym2);
1125 obj.set_at(0, first_syn);
1126 obj.push(VVal::new_str_mv(value.v_(1).s_raw()));
1127 obj
1128
1129 } else if first_syn.get_syn() == Syntax::GetSym2 && value.v_(0).get_syn() == Syntax::Str {
1130 first_syn.set_syn(Syntax::GetSym3);
1131 obj.set_at(0, first_syn);
1132 obj.push(VVal::new_str_mv(value.v_(1).s_raw()));
1133 obj
1134
1135 } else {
1136 if value.v_(0).get_syn() == Syntax::Key {
1137 let call = ps.syn(Syntax::GetSym);
1138 call.push(obj);
1139 call.push(value.v_(1));
1140 call
1141
1142 } else if value.v_(0).get_syn() == Syntax::Str {
1143 let call = ps.syn(Syntax::GetSym);
1144 call.push(obj);
1145 call.push(VVal::new_str_mv(value.v_(1).s_raw()));
1146 call
1147
1148 } else if value.is_int() {
1149 let call = ps.syn(Syntax::GetIdx);
1150 call.push(obj);
1151 call.push(value);
1152 call
1153
1154 } else {
1155 let call = ps.syn(Syntax::GetKey);
1156 call.push(obj);
1157 call.push(value);
1158 call
1159 }
1160 }
1161}
1162
1163fn parse_field_access(obj_val: VVal, ps: &mut State) -> Result<VVal, ParseError> {
1164 let mut obj = obj_val;
1165
1166 while let Some(c) = ps.peek() {
1167 if c != '.' { break; }
1168
1169 ps.consume_wsc();
1170
1171 let c = if let Some(c) = ps.peek() {
1172 c
1173 } else {
1174 return Err(ps.err(ParseErrorKind::EOF("field access")));
1175 };
1176
1177 let value =
1178 if c.is_digit(10) {
1179 let idx = ps.take_while(|c| c.is_digit(10)).to_string();
1180 if let Ok(idx_num) = idx.parse::<i64>() {
1181 ps.skip_ws_and_comments();
1182 VVal::Int(idx_num)
1183 } else {
1184 return Err(ps.err(ParseNumberError::InvalidIndexDigits(idx)));
1185 }
1186
1187 } else if is_ident_start(c) {
1188 let id = ps.syn(Syntax::Key);
1189 id.push(VVal::new_sym_mv(parse_identifier(ps)?));
1190 id
1191 } else {
1192 parse_value(ps)?
1193 };
1194
1195 if let Some(c) = ps.peek() {
1196 let op = ps.peek_op_ws_la("=");
1197
1198 match c {
1199 _ if op.is_some() => {
1200 let op = op.unwrap();
1201 let op_len = op.len();
1202 let binop = make_binop(ps, op);
1203
1204 ps.consume_wsc_n(op_len);
1205 ps.consume_wsc(); let get_value =
1208 optimize_get_key(ps, obj.clone(), value.clone());
1209
1210 let field_set = ps.syn(Syntax::SetKey);
1211 field_set.push(obj);
1212 field_set.push(value);
1213 field_set.push(
1214 reform_binop(construct_op(binop, get_value, parse_expr(ps)?)));
1215
1216 return Ok(field_set);
1217 },
1218 '=' => {
1219 if ps.peek_op().is_none() {
1220 ps.consume_wsc();
1221 let field_set = ps.syn(Syntax::SetKey);
1222 field_set.push(obj);
1223 field_set.push(value);
1224 field_set.push(parse_expr(ps)?);
1225 return Ok(field_set);
1226 }
1227 },
1228 '[' => {
1229 let call = optimize_get_key(ps, obj, value);
1230
1231 let mut field_call = make_to_call(ps, call);
1232 match parse_arg_list(&mut field_call, ps) {
1233 Ok(_) => return Ok(field_call),
1234 Err(err) => return Err(err),
1235 }
1236 },
1237 _ => { }
1238 }
1239 }
1240
1241 obj = optimize_get_key(ps, obj, value);
1242 }
1243
1244 Ok(obj)
1245}
1246
1247fn parse_arg_list<'a, 'b>(call: &'a mut VVal, ps: &'b mut State) -> Result<&'a mut VVal, ParseError> {
1248 if !ps.consume_if_eq_wsc('[') {
1249 return Err(ps.err(ParseErrorKind::ExpectedToken('[', "call arguments start")));
1250 }
1251
1252 let is_apply = ps.consume_if_eq_wsc('[');
1253
1254 if is_apply {
1255 if let VVal::Syn(mut sp) = call.at(0).unwrap_or(VVal::None) {
1256 sp.set_syn(Syntax::Apply);
1257 call.set_at(0, VVal::Syn(sp));
1258 }
1259 let call_argv = parse_expr(ps)?;
1260 call.push(call_argv);
1261
1262 } else {
1263 while let Some(c) = ps.peek() {
1264 if c == ']' { break; }
1265
1266 let call_arg = parse_expr(ps)?;
1267 call.push(call_arg);
1268
1269 if !ps.consume_if_eq_wsc(',') {
1270 break;
1271 }
1272 }
1273 }
1274
1275 if ps.at_end() {
1276 return Err(ps.err(ParseErrorKind::EOF("call args")));
1277 }
1278
1279 if is_apply && !ps.consume_if_eq_wsc(']') {
1280 return Err(ps.err(ParseErrorKind::ExpectedToken(']', "apply arguments end")));
1281 }
1282
1283 if !ps.consume_if_eq_wsc(']') {
1284 return Err(ps.err(ParseErrorKind::ExpectedToken(']', "call arguments end")));
1285 }
1286
1287 Ok(call)
1288}
1289
1290fn get_op_binding_power(ps: &State, op: StrPart) -> Result<(i32, i32), ParseError> {
1291 if op == "&>"
1292 || op == "&@>" { Ok((56, 57)) }
1293 else if op == "<&"
1294 || op == "<@&" { Ok((55, 54)) }
1295 else if op == "//"
1296 || op == "/?"
1297 || op == "/$n"
1298 || op == "/$e"
1299 || op == "/$o" { Ok((52, 53)) }
1300 else if op == "^" { Ok((50, 51)) }
1301 else if op == "*"
1302 || op == "/"
1303 || op == "%" { Ok((48, 49)) }
1304 else if op == "+"
1305 || op == "-" { Ok((46, 47)) }
1306 else if op == "<<"
1307 || op == ">>" { Ok((44, 45)) }
1308 else if op == "<"
1309 || op == ">"
1310 || op == ">="
1311 || op == "<=" { Ok((42, 43)) }
1312 else if op == "=="
1313 || op == "!=" { Ok((40, 41)) }
1314 else if op == "&" { Ok((29, 30)) }
1315 else if op == "&^" { Ok((27, 28)) }
1316 else if op == "&|" { Ok((25, 26)) }
1317 else if op == "&and" { Ok((23, 24)) }
1318 else if op == "&or" { Ok((21, 22)) }
1319 else if op == "=>" { Ok((20, 19)) }
1320 else if op == "+>" { Ok((10, 11)) }
1321 else if op == "<+" { Ok(( 9, 8)) }
1322 else if op == "%>" { Ok(( 6, 7)) }
1323 else if op == "<%" { Ok(( 5, 4)) }
1324 else {
1325 let c = op.to_string().chars().next().unwrap_or(' ');
1326 Err(ps.err(ParseErrorKind::UnexpectedToken(c, "Operator")))
1327 }
1328}
1329
1330fn reform_binop(op: VVal) -> VVal {
1331 match op.v_(0).get_syn() {
1332 Syntax::OpColAddL => {
1333 op.unshift(op.v_(0));
1334 op.set_syn_at(0, Syntax::Call);
1335 op
1336 },
1337 Syntax::OpColAddR => {
1338 op.unshift(op.v_(0));
1339 op.set_syn_at(0, Syntax::Call);
1340 op
1341 },
1342 _ => op
1343 }
1344}
1345
1346fn construct_op(binop: VVal, left: VVal, right: VVal) -> VVal {
1347 match binop.at(0).unwrap().get_syn() {
1348 Syntax::OpNewPair => VVal::pair(left, right),
1349 Syntax::OpCallApplyLwR => {
1350 binop.set_syn_at(0, Syntax::Apply);
1351 binop.push(left);
1352 binop.push(right);
1353 binop
1354 },
1355 Syntax::OpCallLwR => {
1356 binop.set_syn_at(0, Syntax::Call);
1357 binop.push(left);
1358 binop.push(right);
1359 binop
1360 },
1361 Syntax::OpCallApplyRwL => {
1362 binop.set_syn_at(0, Syntax::Apply);
1363 binop.push(right);
1364 binop.push(left);
1365 binop
1366 },
1367 Syntax::OpCallRwL => {
1368 binop.set_syn_at(0, Syntax::Call);
1369 binop.push(right);
1370 binop.push(left);
1371 binop
1372 },
1373 Syntax::OpColAddL => {
1374 if right.v_(0).get_syn() == Syntax::OpColAddL {
1375 right.push(left);
1376 right
1377 } else {
1378 binop.push(right);
1379 binop.push(left);
1380 binop
1381 }
1382 },
1383 Syntax::OpColAddR => {
1384 if left.v_(0).get_syn() == Syntax::OpColAddR {
1385 left.push(right);
1386 left
1387} else {
1394 binop.push(left);
1395 binop.push(right);
1396 binop
1397 }
1398 },
1399 _ => {
1400 binop.push(left);
1401 binop.push(right);
1402 binop
1403 }
1404 }
1405}
1406
1407fn parse_binop(left: Option<VVal>, ps: &mut State, bind_pow: i32)
1408 -> Result<VVal, ParseError>
1409{
1410 let mut left =
1411 if let Some(l) = left { l }
1412 else { parse_call(ps, true)? };
1413
1414 while let Some(op) = ps.peek_op() {
1415 let (l_bp, r_bp) = get_op_binding_power(ps, op)?;
1416 if l_bp < bind_pow {
1417 break;
1418 }
1419
1420 let binop = make_binop(ps, op);
1421 let op_len = op.len();
1422 ps.consume_wsc_n(op_len);
1423
1424 let right = parse_binop(None, ps, r_bp)?;
1425 left = construct_op(binop, left, right);
1426 }
1427
1428 Ok(left)
1429}
1430
1431fn parse_call(ps: &mut State, binop_mode: bool) -> Result<VVal, ParseError> {
1432 let call_indent = ps.indent_pos();
1434 let mut value = parse_value(ps)?;
1436
1437 if ps.lookahead_one_of(";),]}|") || ps.at_end() {
1441 return Ok(value);
1442 }
1443
1444 let mut res_call = VVal::None;
1445
1446 while let Some(c) = ps.peek() {
1447 let op = ps.peek_op();
1448
1449 match c {
1450 '[' => {
1451 let mut call = make_to_call(ps, value);
1452 match parse_arg_list(&mut call, ps) {
1453 Ok(_) => { value = call; },
1454 Err(err) => return Err(err),
1455 }
1456 },
1457 '.' => {
1458 value = parse_field_access(value, ps)?;
1459 },
1460 '~' => {
1461 if binop_mode { break; }
1462
1463 ps.consume_wsc();
1464 if let VVal::None = res_call { res_call = make_to_call(ps, value); }
1465 else { res_call.push(value); }
1466 res_call.push(parse_expr(ps)?);
1467 return Ok(res_call);
1471 },
1472 ';' | ')' | ',' | ']' | '|' | '}' => {
1473 break;
1474 },
1475 _ if op.is_some() => {
1476 if binop_mode { break; }
1477
1478value = reform_binop(parse_binop(Some(value), ps, 0)?);
1490 },
1491 '=' => { break; }, _ => {
1493 if binop_mode { break; }
1494
1495 if let VVal::None = res_call { res_call = make_to_call(ps, value); }
1496 else { res_call.push(value); }
1497
1498 if !ps.indent_pos().belongs_to(&call_indent) {
1500 return Err(ps.err(ParseErrorKind::BadIndent(
1501 "Call argument does not belong to call, it needs a higher indentation.")));
1502 }
1503
1504 value = parse_value(ps)?;
1505 },
1506 }
1507 }
1508
1509 if let VVal::None = res_call {
1510 res_call = value;
1511 } else {
1512 res_call.push(value);
1513 }
1514
1515 Ok(res_call)
1516}
1517
1518fn parse_expr(ps: &mut State) -> Result<VVal, ParseError> {
1519 let mut call = parse_call(ps, false)?;
1520 if ps.at_end() {
1521 return Ok(call);
1522 }
1523
1524 while let Some(c) = ps.peek() {
1525 match c {
1526 '|' => {
1527 if ps.lookahead("|>") {
1528 ps.consume();
1529 ps.consume_wsc();
1530
1531 let call_right = parse_call(ps, false)?;
1532
1533 let new_call = make_to_call(ps, call);
1534 new_call.push(call_right);
1535 call = new_call;
1536
1537 } else {
1538 let push_front =
1539 if ps.lookahead("||") { ps.consume(); true } else { false };
1540 ps.consume_wsc();
1541
1542 let mut fn_expr = parse_call(ps, false)?;
1543 if !is_call(&fn_expr) {
1544 fn_expr = make_to_call(ps, fn_expr);
1545 }
1546
1547 if push_front {
1548 fn_expr.insert_at(2, call);
1549 } else {
1550 fn_expr.push(call);
1551 }
1552
1553 call = fn_expr;
1554 }
1555 },
1556 _ => {
1557 break;
1558 }
1559 }
1560 }
1561
1562 Ok(call)
1563}
1564
1565#[allow(clippy::unnecessary_unwrap)]
1566#[allow(clippy::collapsible_else_if)]
1567fn parse_assignment(ps: &mut State, is_def: bool) -> Result<VVal, ParseError> {
1568 if ps.at_end() {
1569 return Err(ps.err(ParseErrorKind::EOF("assignment")));
1570 }
1571
1572 let mut assign = VVal::vec();
1573 if is_def {
1574 assign.push(ps.syn_raw(Syntax::Def));
1575 } else {
1576 assign.push(ps.syn_raw(Syntax::Assign));
1577 }
1578
1579 let mut is_ref = false;
1580
1581 if is_def {
1582 if ps.consume_if_eq_wsc(':') {
1583 let key = parse_identifier(ps)?;
1584 if key == "global" {
1585 assign = ps.syn(Syntax::DefGlobRef);
1586 } else if key == "const" {
1587 assign = ps.syn(Syntax::DefConst);
1588 }
1589 }
1590 } else {
1591 if ps.consume_if_eq_wsc('*') {
1592 assign = ps.syn(Syntax::AssignRef);
1593 is_ref = true;
1594 }
1595 }
1596
1597 let mut destructuring = false;
1598 let ids = VVal::vec();
1599
1600 match ps.expect_some(ps.peek())? {
1601 '(' => {
1602 ps.consume_wsc();
1603 destructuring = true;
1604
1605 while let Some(c) = ps.peek() {
1606 if c == ')' { break; }
1607 ids.push(VVal::new_sym_mv(parse_identifier(ps)?));
1608 if !ps.consume_if_eq_wsc(',') { break; }
1609 }
1610
1611 if ps.at_end() {
1612 return Err(ps.err(ParseErrorKind::EOF(
1613 "destructuring assignment")));
1614 }
1615
1616 if !ps.consume_if_eq_wsc(')') {
1617 return Err(ps.err(ParseErrorKind::ExpectedToken(
1618 ')', "destructuring assignment end")));
1619 }
1620 },
1621 _ => { ids.push(VVal::new_sym_mv(parse_identifier(ps)?)); }
1622 }
1623
1624
1625 let op = ps.peek_op_ws_la("=");
1626 if !is_def && !destructuring && op.is_some() && ids.len() == 1 {
1627 let op = op.unwrap();
1628 let op_len = op.len();
1629 let binop = make_binop(ps, op);
1630 ps.consume_wsc_n(op_len);
1631 ps.consume_wsc(); let mut var =
1634 ids.at(0).unwrap().with_s_ref(|var_name|
1635 make_var(ps, var_name));
1636
1637 if is_ref {
1638 let r = ps.syn(Syntax::Deref);
1639 r.push(var);
1640 var = r;
1641 }
1642
1643 assign.push(ids);
1644 assign.push(
1645 reform_binop(construct_op(binop, var, parse_expr(ps)?)));
1646
1647 return Ok(assign);
1648
1649 } else if !ps.consume_if_eq_wsc('=') {
1650 return Err(ps.err(ParseErrorKind::ExpectedToken('=', "assignment")));
1651 }
1652
1653 assign.push(ids);
1654
1655 assign.push(parse_expr(ps)?);
1656
1657 if destructuring {
1658 assign.push(VVal::Bol(destructuring));
1659 }
1660
1661 Ok(assign)
1662}
1663
1664fn parse_stmt(ps: &mut State) -> Result<VVal, ParseError> {
1665 match ps.peek() {
1667 Some(c) => {
1668 match c {
1669 '!' => {
1670 ps.consume_wsc();
1671 if ps.consume_if_eq_wsc('@') {
1672 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("special assignment"))); }
1673 let id = parse_identifier(ps)?;
1674 match &id[..] {
1675 "wlambda" => {
1676 let imp = ps.syn(Syntax::Import);
1677 imp.push(VVal::None);
1678 imp.push(VVal::new_sym("wlambda"));
1679 Ok(imp)
1680 },
1681 "import" => {
1682 let prefix =
1683 VVal::new_sym_mv(parse_identifier(ps)?);
1684 ps.skip_ws_and_comments();
1685 let name =
1686 if ps.peek().unwrap_or(';') == ';' {
1687 prefix.clone()
1688 } else {
1689 ps.consume_if_eq_wsc('=');
1690 VVal::new_sym_mv(parse_identifier(ps)?)
1691 };
1692
1693 let imp = ps.syn(Syntax::Import);
1694 imp.push(prefix);
1695 imp.push(name);
1696 Ok(imp)
1697 },
1698 "export" => {
1699 let name = parse_identifier(ps)?;
1700 ps.skip_ws_and_comments();
1701 ps.consume_if_eq_wsc('=');
1702 let expr = parse_expr(ps)?;
1703 let exp = ps.syn(Syntax::Export);
1704 exp.push(VVal::new_sym_mv(name));
1705 exp.push(expr);
1706 Ok(exp)
1707 },
1708 "dump_stack" => Ok(ps.syn(Syntax::DumpStack)),
1709 "dump_vm" => Ok(ps.syn(Syntax::DumpVM)),
1710 _ => Err(ps.err(ParseErrorKind::BadKeyword(id.to_string(), "import or export"))),
1711 }
1712 } else {
1713 parse_assignment(ps, true)
1714 }
1715 },
1716 '.' => {
1717 ps.consume_wsc();
1718 parse_assignment(ps, false)
1719 }
1720 _ => parse_expr(ps),
1721 }
1722 },
1723 None => Err(ps.err(ParseErrorKind::EOF("statement")))
1724 }
1725}
1726
1727fn parse_arity(ps: &mut State) -> Result<VVal, ParseError> {
1729 if !ps.consume_if_eq_wsc('|') {
1730 return Err(ps.err(
1731 ParseErrorKind::ExpectedToken('|', "arity definition start")));
1732 }
1733
1734 if ps.at_end() { return Err(ps.err(ParseErrorKind::EOF("parsing arity definition"))); }
1735
1736 let arity = if ps.expect_some(ps.peek())? != '|' {
1737 let min = parse_num(ps)?;
1738 if !min.is_int() {
1739 return Err(ps.err(ParseValueError::ExpectedMinArity));
1740 }
1741
1742 let max = if ps.consume_if_eq_wsc('<') {
1743 let max = parse_num(ps)?;
1744 if !max.is_int() {
1745 return Err(ps.err(ParseValueError::ExpectedMaxArity));
1746 }
1747 max
1748 } else {
1749 min.clone()
1750 };
1751
1752 let arity = VVal::vec();
1753 arity.push(min);
1754 arity.push(max);
1755 arity
1756 } else {
1757 let arity = VVal::vec();
1758 arity.push(VVal::Bol(true));
1759 arity.push(VVal::Bol(true));
1760 arity
1761 };
1762
1763 if !ps.consume_if_eq_wsc('|') {
1764 return Err(ps.err(ParseErrorKind::ExpectedToken(
1765 '|', "arity definition end")));
1766 }
1767
1768 Ok(arity)
1769}
1770
1771pub fn parse_block(ps: &mut State, with_arity: bool, delimited: bool, end_delim: bool) -> Result<VVal, ParseError> {
1796 if delimited {
1797 if !ps.consume_if_eq_wsc('{') {
1798 return Err(ps.err(ParseErrorKind::ExpectedToken('{', "block start")));
1799 }
1800 }
1801
1802 let block = ps.syn(Syntax::Block);
1803
1804 if with_arity && ps.lookahead("|") {
1805 block.push(parse_arity(ps)?);
1806 } else if with_arity {
1807 block.push(VVal::None);
1808 }
1809
1810 while let Some(c) = ps.peek() {
1811 if end_delim { if c == '}' { break; } }
1812
1813 let next_stmt = parse_stmt(ps)?;
1814 block.push(next_stmt);
1815
1816 while ps.consume_if_eq_wsc(';') {
1817 while ps.consume_if_eq_wsc(';') { }
1818 if ps.at_end() || (end_delim && ps.peek().unwrap_or(' ') == '}') {
1819 if delimited {
1820 ps.consume_if_eq_wsc('}');
1821 }
1822 return Ok(block);
1823 }
1824 let next_stmt = parse_stmt(ps)?;
1825 block.push(next_stmt);
1826 }
1827 }
1828
1829 if delimited {
1830 if ps.at_end() {
1831 return Err(ps.err(ParseErrorKind::EOF("parsing block")));
1832 }
1833 if !ps.consume_if_eq_wsc('}') {
1834 return Err(ps.err(ParseErrorKind::ExpectedToken('}', "block end")));
1835 }
1836 }
1837
1838 Ok(block)
1839}
1840
1841pub fn parse(s: &str, filename: &str) -> Result<VVal, String> {
1852 let mut ps = State::new(s, filename);
1853 parse_block(&mut ps, false, false, true).map_err(|e| format!("{}", e))
1854}
1855
1856#[cfg(test)]
1857mod tests {
1858 use super::*;
1859
1860 fn parse(s: &str) -> String {
1861 let mut ps = State::new(s, "<parser_test>");
1862 match parse_block(&mut ps, false, false, true) {
1863 Ok(v) => v.s(),
1864 Err(e) => panic!("Parse error: {}", e),
1865 }
1866 }
1867
1868 fn parse_error(s: &str) -> String {
1869 let mut ps = State::new(s,"<parser_test>");
1870 match parse_block(&mut ps, false, false, true) {
1871 Ok(v) => panic!("Expected error but got result: {} for input '{}'",
1872 v.s(), s),
1873 Err(e) => format!("Parse error: {}", e),
1874 }
1875 }
1876
1877 #[test]
1878 fn check_parse_numbers() {
1879 assert_eq!(parse("#comment \n10;#fom \n"), "$[$%:Block,10]");
1880 assert_eq!(parse("10;"), "$[$%:Block,10]");
1881 assert_eq!(parse("10.123;"), "$[$%:Block,10.123]");
1882 assert_eq!(parse("-10;"), "$[$%:Block,-10]");
1883 assert_eq!(parse("-0xFF;"), "$[$%:Block,-255]");
1884 assert_eq!(parse("-0xFF.1;"), "$[$%:Block,-255.0625]");
1885 assert_eq!(parse("-0xFF.9;"), "$[$%:Block,-255.5625]");
1886 assert_eq!(parse("-0xFF.A;"), "$[$%:Block,-255.625]");
1887 assert_eq!(parse("-0xFF.F;"), "$[$%:Block,-255.9375]");
1888 }
1889
1890 #[test]
1891 fn check_parse_sym() {
1892 assert_eq!(parse(":\"foo bar\""),
1893 "$[$%:Block,$[$%:Key,:\"foo bar\"]]");
1894 assert_eq!(parse("foo :bar -2.3 2.3"),
1895 "$[$%:Block,$[$%:Call,$[$%:Var,:foo],$[$%:Key,:bar],-2.3,2.3]]");
1896 assert_eq!(parse("foo :bar -x 2"),
1897 "$[$%:Block,$[$%:Call,$[$%:Var,:foo],$[$%:BinOpSub,$[$%:Key,:bar],$[$%:Var,:x]],2]]");
1898 assert_eq!(parse("foo :bar -2 2"),
1899 "$[$%:Block,$[$%:Call,$[$%:Var,:foo],$[$%:Key,:bar],-2,2]]");
1900 }
1901
1902 #[test]
1903 fn check_parse_vec() {
1904 assert_eq!(parse("$[10];"),
1905 "$[$%:Block,$[$%:Lst,10]]");
1906 assert_eq!(parse("$[10, 11.23, -30, -0xFF];"),
1907 "$[$%:Block,$[$%:Lst,10,11.23,-30,-255]]");
1908 assert_eq!(parse("$[10, $[1,2,3], 11.23, -30, -0xFF];"),
1909 "$[$%:Block,$[$%:Lst,10,$[$%:Lst,1,2,3],11.23,-30,-255]]");
1910 }
1911
1912 #[test]
1913 fn check_parse_last_commas() {
1914 assert_eq!(parse("$[10,]"), "$[$%:Block,$[$%:Lst,10]]");
1915 assert_eq!(parse("$[10,20,]"), "$[$%:Block,$[$%:Lst,10,20]]");
1916 assert_eq!(parse("${a=1,b=2,}"), "$[$%:Block,$[$%:Map,$[:a,1],$[:b,2]]]");
1917 assert_eq!(parse("${a=1,}"), "$[$%:Block,$[$%:Map,$[:a,1]]]");
1918 assert_eq!(parse("f[1,]"), "$[$%:Block,$[$%:Call,$[$%:Var,:f],1]]");
1919 }
1920
1921 #[test]
1922 fn check_calls() {
1923 assert_eq!(parse("10"), "$[$%:Block,10]");
1924 assert_eq!(parse("10;"), "$[$%:Block,10]");
1925 assert_eq!(parse("10; 20"), "$[$%:Block,10,20]");
1926 assert_eq!(parse("10;;; 20"), "$[$%:Block,10,20]");
1927 assert_eq!(parse("10;;; 20;"), "$[$%:Block,10,20]");
1928 assert_eq!(parse("10 20;"), "$[$%:Block,$[$%:Call,10,20]]");
1929 assert_eq!(parse("(10) 20;"), "$[$%:Block,$[$%:Call,10,20]]");
1930 }
1931
1932 #[test]
1933 fn check_expr() {
1934 assert_eq!(parse("10 20 30"),
1935 "$[$%:Block,$[$%:Call,10,20,30]]");
1936 assert_eq!(parse("10 20 30 40"),
1937 "$[$%:Block,$[$%:Call,10,20,30,40]]");
1938 assert_eq!(parse("10 || 20 30"),
1939 "$[$%:Block,$[$%:Call,20,10,30]]");
1940 assert_eq!(parse("10 | 20 30"),
1941 "$[$%:Block,$[$%:Call,20,30,10]]");
1942 assert_eq!(parse("10 20 | 30 40"),
1943 "$[$%:Block,$[$%:Call,30,40,$[$%:Call,10,20]]]");
1944 assert_eq!(parse("10 20 || 30 40"),
1945 "$[$%:Block,$[$%:Call,30,$[$%:Call,10,20],40]]");
1946 assert_eq!(parse("10 20 | 30 40 | 50"),
1947 "$[$%:Block,$[$%:Call,50,$[$%:Call,30,40,$[$%:Call,10,20]]]]");
1948 assert_eq!(parse("10 | 20 | 30 | 40"),
1949 "$[$%:Block,$[$%:Call,40,$[$%:Call,30,$[$%:Call,20,10]]]]");
1950 assert_eq!(parse("10[] | 20 | 30 | 40"),
1951 "$[$%:Block,$[$%:Call,40,$[$%:Call,30,$[$%:Call,20,$[$%:Call,10]]]]]");
1952 assert_eq!(parse("10[][] | 20 | 30 | 40"),
1953 "$[$%:Block,$[$%:Call,40,$[$%:Call,30,$[$%:Call,20,$[$%:Call,$[$%:Call,10]]]]]]");
1954 assert_eq!(parse("(10 | 20) | (foo(bar))"),
1955 "$[$%:Block,$[$%:Call,$[$%:Var,:foo],$[$%:Var,:bar],$[$%:Call,20,10]]]");
1956 assert_eq!(parse("10 ~ 20 ~ 30 ~ 40"),
1957 "$[$%:Block,$[$%:Call,10,$[$%:Call,20,$[$%:Call,30,40]]]]");
1958 assert_eq!(parse("10 | 20"), "$[$%:Block,$[$%:Call,20,10]]");
1959 assert_eq!(parse("10 (1 2) (3 4 5) (6 (7))"), "$[$%:Block,$[$%:Call,10,$[$%:Call,1,2],$[$%:Call,3,4,5],$[$%:Call,6,7]]]");
1960 assert_eq!(parse("10[]"), "$[$%:Block,$[$%:Call,10]]");
1961 assert_eq!(parse("10[20, 30]"), "$[$%:Block,$[$%:Call,10,20,30]]");
1962 assert_eq!(parse("10 x[20, 30]"), "$[$%:Block,$[$%:Call,10,$[$%:Call,$[$%:Var,:x],20,30]]]");
1963 assert_eq!(parse("10 x[20, 30] | 50"), "$[$%:Block,$[$%:Call,50,$[$%:Call,10,$[$%:Call,$[$%:Var,:x],20,30]]]]");
1964 assert_eq!(parse("(10).(\"a\" \"b\")"), "$[$%:Block,$[$%:GetKey,10,$[$%:Call,$[$%:Str,\"a\"],$[$%:Str,\"b\"]]]]");
1965 assert_eq!(parse("(10).(\"ab\")"), "$[$%:Block,$[$%:GetSym,10,\"ab\"]]");
1966 assert_eq!(parse("(10).a"), "$[$%:Block,$[$%:GetSym,10,:a]]");
1967 assert_eq!(parse("a.b"), "$[$%:Block,$[$%:GetSym,$[$%:Var,:a],:b]]");
1968 assert_eq!(parse("10 a.b"), "$[$%:Block,$[$%:Call,10,$[$%:GetSym,$[$%:Var,:a],:b]]]");
1969 assert_eq!(parse("(10).(20)"), "$[$%:Block,$[$%:GetIdx,10,20]]");
1970 assert_eq!(parse("10.20 30"), "$[$%:Block,$[$%:Call,10.2,30]]");
1971 assert_eq!(parse("10 20 ~ 30 ~ 40 ~ 50"), "$[$%:Block,$[$%:Call,10,20,$[$%:Call,30,$[$%:Call,40,50]]]]");
1972 assert_eq!(parse("10 20 ~ 30 40 ~ 40 1 2 3 ~ 50 60"), "$[$%:Block,$[$%:Call,10,20,$[$%:Call,30,40,$[$%:Call,40,1,2,3,$[$%:Call,50,60]]]]]");
1973 assert_eq!(parse("10[10[1,2,3 foo] ~ 4]"), "$[$%:Block,$[$%:Call,10,$[$%:Call,$[$%:Call,10,1,2,$[$%:Call,3,$[$%:Var,:foo]]],4]]]");
1974 assert_eq!(parse("foo.b.c.d"), "$[$%:Block,$[$%:GetSym3,$[$%:Var,:foo],:b,:c,:d]]");
1975 assert_eq!(parse("foo.b.c.d[]"), "$[$%:Block,$[$%:Call,$[$%:GetSym3,$[$%:Var,:foo],:b,:c,:d]]]");
1976 assert_eq!(parse("foo.b.c.d[1,2,3]"), "$[$%:Block,$[$%:Call,$[$%:GetSym3,$[$%:Var,:foo],:b,:c,:d],1,2,3]]");
1977 assert_eq!(parse("foo.b.c.d 1 2 3"), "$[$%:Block,$[$%:Call,$[$%:GetSym3,$[$%:Var,:foo],:b,:c,:d],1,2,3]]");
1978 assert_eq!(parse("(foo.b.c.d) 1 2 3"), "$[$%:Block,$[$%:Call,$[$%:GetSym3,$[$%:Var,:foo],:b,:c,:d],1,2,3]]");
1979 assert_eq!(parse("foo.a = 10"), "$[$%:Block,$[$%:SetKey,$[$%:Var,:foo],$[$%:Key,:a],10]]");
1980 assert_eq!(parse("foo.a = 10 | 20"), "$[$%:Block,$[$%:SetKey,$[$%:Var,:foo],$[$%:Key,:a],$[$%:Call,20,10]]]");
1981 assert_eq!(parse("foo.a = 10 ~ 20"), "$[$%:Block,$[$%:SetKey,$[$%:Var,:foo],$[$%:Key,:a],$[$%:Call,10,20]]]");
1982 assert_eq!(parse("4 == 5 ~ 10"), "$[$%:Block,$[$%:Call,$[$%:BinOpEq,4,5],10]]");
1983 assert_eq!(parse("foo.(i) = 10"), "$[$%:Block,$[$%:SetKey,$[$%:Var,:foo],$[$%:Var,:i],10]]");
1984 assert_eq!(parse("foo :x :y 10"), "$[$%:Block,$[$%:Call,$[$%:Var,:foo],$[$%:Key,:x],$[$%:Key,:y],10]]");
1985 }
1986
1987 #[test]
1988 fn check_expr_err() {
1989 assert_eq!(parse_error("foo.a[] = 10"),
1990 "Parse error: <parser_test>:1:9 Expected literal value, sub expression, block, key or identifier\nat code:\n1 | = 10\n");
1991 }
1992
1993 #[test]
1994 fn check_identifier() {
1995 assert_eq!(parse("+"), "$[$%:Block,$[$%:Var,:+]]");
1996 assert_eq!(parse("-"), "$[$%:Block,$[$%:Var,:-]]");
1997 assert_eq!(parse("+ 10 20"), "$[$%:Block,$[$%:Call,$[$%:Var,:+],10,20]]");
1998 assert_eq!(parse("13 + 10 20"), "$[$%:Block,$[$%:Call,$[$%:BinOpAdd,13,10],20]]");
1999 assert_eq!(parse("13 + 10 == 23"),
2000 "$[$%:Block,$[$%:BinOpEq,$[$%:BinOpAdd,13,10],23]]");
2001 assert_eq!(parse("(+ 12 ~ - 24 23) == 13"),
2002 "$[$%:Block,$[$%:BinOpEq,$[$%:Call,$[$%:Var,:+],12,$[$%:Call,$[$%:Var,:-],24,23]],13]]");
2003 assert_eq!(parse("_"), "$[$%:Block,$[$%:Var,:_]]");
2004 assert_eq!(parse("ten"), "$[$%:Block,$[$%:Var,:ten]]");
2005 assert_eq!(parse("tenäß foo"), "$[$%:Block,$[$%:Call,$[$%:Var,:tenäß],$[$%:Var,:foo]]]");
2006 }
2007
2008 #[test]
2009 fn check_primitives() {
2010 assert_eq!(parse("$n"), "$[$%:Block,$n]");
2011 assert_eq!(parse("$none"), "$[$%:Block,$n]");
2012 assert_eq!(parse("$t"), "$[$%:Block,$true]");
2013 assert_eq!(parse("$true"), "$[$%:Block,$true]");
2014 assert_eq!(parse("$f"), "$[$%:Block,$false]");
2015 assert_eq!(parse("$false"), "$[$%:Block,$false]");
2016 }
2017
2018 #[test]
2019 fn check_binops() {
2020 assert_eq!(parse("20 * 10"), "$[$%:Block,$[$%:BinOpMul,20,10]]");
2021 assert_eq!(parse("20 + 10"), "$[$%:Block,$[$%:BinOpAdd,20,10]]");
2022 assert_eq!(parse("20 - 10"), "$[$%:Block,$[$%:BinOpSub,20,10]]");
2023 assert_eq!(parse("20 / 10"), "$[$%:Block,$[$%:BinOpDiv,20,10]]");
2024 assert_eq!(parse("20 % 10"), "$[$%:Block,$[$%:BinOpMod,20,10]]");
2025 assert_eq!(parse("20 > 10"), "$[$%:Block,$[$%:BinOpGt,20,10]]");
2026 assert_eq!(parse("20 < 10"), "$[$%:Block,$[$%:BinOpLt,20,10]]");
2027 assert_eq!(parse("20 <= 10"), "$[$%:Block,$[$%:BinOpLe,20,10]]");
2028 assert_eq!(parse("20 >= 10"), "$[$%:Block,$[$%:BinOpGe,20,10]]");
2029 assert_eq!(parse("20 // 10"), "$[$%:Block,$[$%:BinOpSomeOr,20,10]]");
2030 assert_eq!(parse("20 /? 10"), "$[$%:Block,$[$%:BinOpExtSomeOr,20,10]]");
2031 assert_eq!(parse("20 /$e 10"), "$[$%:Block,$[$%:BinOpErrOr,20,10]]");
2032 assert_eq!(parse("20 /$o 10"), "$[$%:Block,$[$%:BinOpOptOr,20,10]]");
2033 assert_eq!(parse("20 /$n 10"), "$[$%:Block,$[$%:BinOpNoneOr,20,10]]");
2034 assert_eq!(parse("40 20 * 10"), "$[$%:Block,$[$%:Call,40,$[$%:BinOpMul,20,10]]]");
2035 assert_eq!(parse("40 20 * 10 30"), "$[$%:Block,$[$%:Call,40,$[$%:BinOpMul,20,10],30]]");
2036 assert_eq!(parse("40 20 * 10[]"), "$[$%:Block,$[$%:Call,40,$[$%:BinOpMul,20,$[$%:Call,10]]]]");
2037 assert_eq!(parse("40 20[] * 10[]"), "$[$%:Block,$[$%:Call,40,$[$%:BinOpMul,$[$%:Call,20],$[$%:Call,10]]]]");
2038 assert_eq!(parse("20[] * 10[]"), "$[$%:Block,$[$%:BinOpMul,$[$%:Call,20],$[$%:Call,10]]]");
2039 assert_eq!(parse("10 - 20 * 30"), "$[$%:Block,$[$%:BinOpSub,10,$[$%:BinOpMul,20,30]]]");
2040 assert_eq!(parse("10 * 20 - 30"), "$[$%:Block,$[$%:BinOpSub,$[$%:BinOpMul,10,20],30]]");
2041 assert_eq!(parse("10 * 20 - 30 * 2"), "$[$%:Block,$[$%:BinOpSub,$[$%:BinOpMul,10,20],$[$%:BinOpMul,30,2]]]");
2042 assert_eq!(parse("10 * 20 * 30"), "$[$%:Block,$[$%:BinOpMul,$[$%:BinOpMul,10,20],30]]");
2043 assert_eq!(parse("10 - 20 - 30 - 40"), "$[$%:Block,$[$%:BinOpSub,$[$%:BinOpSub,$[$%:BinOpSub,10,20],30],40]]");
2044 assert_eq!(parse("10 - 20 - (30 - 40)"), "$[$%:Block,$[$%:BinOpSub,$[$%:BinOpSub,10,20],$[$%:BinOpSub,30,40]]]");
2045
2046 assert_eq!(parse("$t &and $f"), "$[$%:Block,$[$%:And,$true,$false]]");
2047 assert_eq!(parse("1 &and 2 &and 3 &and 4"), "$[$%:Block,$[$%:And,$[$%:And,$[$%:And,1,2],3],4]]");
2048 assert_eq!(parse("$t &or $f"), "$[$%:Block,$[$%:Or,$true,$false]]");
2049 assert_eq!(parse("$t &and $f &or $f &and $f"), "$[$%:Block,$[$%:Or,$[$%:And,$true,$false],$[$%:And,$false,$false]]]");
2050
2051 assert_eq!(parse("20 & 10"), "$[$%:Block,$[$%:Call,$[$%:Var,:&],20,10]]");
2052
2053 }
2054
2055 #[test]
2056 fn check_assignments() {
2057 assert_eq!(parse("!x=10;"), "$[$%:Block,$[$%:Def,$[:x],10]]");
2058 assert_eq!(parse("! x = 10 ;"), "$[$%:Block,$[$%:Def,$[:x],10]]");
2059 assert_eq!(parse("! x = 10"), "$[$%:Block,$[$%:Def,$[:x],10]]");
2060 assert_eq!(parse("!:global (y,x) = @"), "$[$%:Block,$[$%:DefGlobRef,$[:y,:x],$[$%:Var,:@],$true]]");
2061 assert_eq!(parse(". (a,b) = 10"), "$[$%:Block,$[$%:Assign,$[:a,:b],10,$true]]");
2062 }
2063
2064 #[test]
2065 fn check_func() {
2066 assert_eq!(parse("{}"), "$[$%:Block,$[$%:Func,$n,$n]]");
2067 assert_eq!(parse("{10;}"), "$[$%:Block,$[$%:Func,$n,$n,10]]");
2068 assert_eq!(parse("{10;;;}"), "$[$%:Block,$[$%:Func,$n,$n,10]]");
2069 assert_eq!(parse("{10; 20}"), "$[$%:Block,$[$%:Func,$n,$n,10,20]]");
2070 assert_eq!(parse("{ 10 } { }"), "$[$%:Block,$[$%:Call,$[$%:Func,$n,$n,10],$[$%:Func,$n,$n]]]");
2071 assert_eq!(parse("\\:x { }"), "$[$%:Block,$[$%:Func,:x,$n]]");
2072 assert_eq!(parse("\\ p 1 | 20 ~ 30"), "$[$%:Block,$[$%:Func,$n,$n,$[$%:Call,20,30,$[$%:Call,$[$%:Var,:p],1]]]]");
2073 }
2074
2075 #[test]
2076 fn check_map() {
2077 assert_eq!(parse("${a=10}"), "$[$%:Block,$[$%:Map,$[:a,10]]]");
2078 assert_eq!(parse("${:a=10}"), "$[$%:Block,$[$%:Map,$[$[$%:Key,:a],10]]]");
2079 }
2080
2081 #[test]
2082 fn check_str() {
2083 assert_eq!(parse("\"foo\""), "$[$%:Block,$[$%:Str,\"foo\"]]");
2084 assert_eq!(parse("$q$foo$"), "$[$%:Block,$[$%:Str,\"foo\"]]");
2085 assert_eq!(parse("\"fo\0o\""), "$[$%:Block,$[$%:Str,\"fo\\0o\"]]");
2086 assert_eq!(parse("\"fo\no\""), "$[$%:Block,$[$%:Str,\"fo\\no\"]]");
2087 assert_eq!(parse("\"fo\ro\""), "$[$%:Block,$[$%:Str,\"fo\\ro\"]]");
2088 assert_eq!(parse("\"fo\\\"o\""), "$[$%:Block,$[$%:Str,\"fo\\\"o\"]]");
2089 assert_eq!(parse("\"fo\x05o\""), "$[$%:Block,$[$%:Str,\"fo\\x05o\\u{9f}\"]]");
2090 assert_eq!(parse("\"fo\x05o\\u{9f}\""), "$[$%:Block,$[$%:Str,\"fo\\x05o\\u{9f}\"]]");
2091 assert_eq!(parse("\"fo\x05o\\u{0009f}\""), "$[$%:Block,$[$%:Str,\"fo\\x05o\\u{9f}\"]]");
2092 assert_eq!(parse("\"fo\x05o\\u{09f}\""), "$[$%:Block,$[$%:Str,\"fo\\x05o\\u{9f}\"]]");
2093 assert_eq!(parse("\"fo\x05o\\u{2400}\""), "$[$%:Block,$[$%:Str,\"fo\\x05o␀\"]]");
2094 assert_eq!(parse("$q foo "), "$[$%:Block,$[$%:Str,\"foo\"]]");
2095 assert_eq!(parse("$q[foo]"), "$[$%:Block,$[$%:Str,\"foo\"]]");
2096 assert_eq!(parse("$q(foo)"), "$[$%:Block,$[$%:Str,\"foo\"]]");
2097 assert_eq!(parse("$q{foo}"), "$[$%:Block,$[$%:Str,\"foo\"]]");
2098 assert_eq!(parse("$q<foo>"), "$[$%:Block,$[$%:Str,\"foo\"]]");
2099
2100 assert_eq!(parse("$b\"\\u{2400}\""), "$[$%:Block,$[$%:Str,$b\"\\xE2\\x90\\x80\"]]");
2101 assert_eq!(parse("$Q'foo'"), "$[$%:Block,$[$%:Str,$b\"foo\"]]");
2102 assert_eq!(parse("$b\"\\x00\\xFF\\xEB\""), "$[$%:Block,$[$%:Str,$b\"\\0\\xFF\\xEB\"]]");
2103 }
2104
2105 #[test]
2106 fn check_parse_field_access() {
2107 assert_eq!(parse("foo.(bar) == 2019"), "$[$%:Block,$[$%:BinOpEq,$[$%:GetKey,$[$%:Var,:foo],$[$%:Var,:bar]],2019]]");
2108 assert_eq!(parse("o.x[]"), "$[$%:Block,$[$%:Call,$[$%:GetSym,$[$%:Var,:o],:x]]]");
2109
2110 assert_eq!(parse("o.1"), "$[$%:Block,$[$%:GetIdx,$[$%:Var,:o],1]]");
2111 assert_eq!(parse("o.1.2"), "$[$%:Block,$[$%:GetIdx2,$[$%:Var,:o],1,2]]");
2112 assert_eq!(parse("o.1.2.3"), "$[$%:Block,$[$%:GetIdx3,$[$%:Var,:o],1,2,3]]");
2113 assert_eq!(parse("o.x"), "$[$%:Block,$[$%:GetSym,$[$%:Var,:o],:x]]");
2114 assert_eq!(parse("o.x.y"), "$[$%:Block,$[$%:GetSym2,$[$%:Var,:o],:x,:y]]");
2115 assert_eq!(parse("o.x.y.z"), "$[$%:Block,$[$%:GetSym3,$[$%:Var,:o],:x,:y,:z]]");
2116 assert_eq!(parse("o.x.(\"y\").z"), "$[$%:Block,$[$%:GetSym3,$[$%:Var,:o],:x,\"y\",:z]]");
2117 assert_eq!(parse("o.(\"x\")"), "$[$%:Block,$[$%:GetSym,$[$%:Var,:o],\"x\"]]");
2118 assert_eq!(parse("o.(\"x\").(\"y\")"), "$[$%:Block,$[$%:GetSym2,$[$%:Var,:o],\"x\",\"y\"]]");
2119 assert_eq!(parse("o.(\"x\").(\"y\").(\"z\")"), "$[$%:Block,$[$%:GetSym3,$[$%:Var,:o],\"x\",\"y\",\"z\"]]");
2120 assert_eq!(parse("o.(1 \"x\")"), "$[$%:Block,$[$%:GetKey,$[$%:Var,:o],$[$%:Call,1,$[$%:Str,\"x\"]]]]");
2121 assert_eq!(parse("o.(1 \"x\").(1 \"y\")"), "$[$%:Block,$[$%:GetKey,$[$%:GetKey,$[$%:Var,:o],$[$%:Call,1,$[$%:Str,\"x\"]]],$[$%:Call,1,$[$%:Str,\"y\"]]]]");
2122 assert_eq!(parse("o.(1 \"x\").(1 \"y\").(1 \"z\")"), "$[$%:Block,$[$%:GetKey,$[$%:GetKey,$[$%:GetKey,$[$%:Var,:o],$[$%:Call,1,$[$%:Str,\"x\"]]],$[$%:Call,1,$[$%:Str,\"y\"]]],$[$%:Call,1,$[$%:Str,\"z\"]]]]");
2123 }
2124
2125 #[test]
2126 fn check_err_val() {
2127 assert_eq!(parse("$e 10 20 30"), "$[$%:Block,$[$%:Err,$[$%:Call,10,20,30]]]");
2128 assert_eq!(parse("$e 10 20 30 | 20"), "$[$%:Block,$[$%:Err,$[$%:Call,20,$[$%:Call,10,20,30]]]]");
2129 }
2130
2131 #[test]
2132 fn check_parse_ref_deref() {
2133 assert_eq!(parse("$& 1"), "$[$%:Block,$[$%:HRef,1]]");
2134 assert_eq!(parse("$&$[1,2]"), "$[$%:Block,$[$%:HRef,$[$%:Lst,1,2]]]");
2135 assert_eq!(parse("$&${z=1}"), "$[$%:Block,$[$%:HRef,$[$%:Map,$[:z,1]]]]");
2136 assert_eq!(parse("$&& 1"), "$[$%:Block,$[$%:Ref,1]]");
2137 assert_eq!(parse("$&&$[1,2]"), "$[$%:Block,$[$%:Ref,$[$%:Lst,1,2]]]");
2138 assert_eq!(parse("$&&${z=1}"), "$[$%:Block,$[$%:Ref,$[$%:Map,$[:z,1]]]]");
2139 assert_eq!(parse("$*${z=1}.f=1"), "$[$%:Block,$[$%:SetKey,$[$%:Deref,$[$%:Map,$[:z,1]]],$[$%:Key,:f],1]]");
2140 assert_eq!(parse("$*xxx.f=1"), "$[$%:Block,$[$%:SetKey,$[$%:Deref,$[$%:Var,:xxx]],$[$%:Key,:f],1]]");
2141 assert_eq!(parse("$*xxx.f"), "$[$%:Block,$[$%:GetSym,$[$%:Deref,$[$%:Var,:xxx]],:f]]");
2142 }
2143
2144 #[test]
2145 fn check_self() {
2146 assert_eq!(parse("$s"), "$[$%:Block,$[$%:SelfObj]]");
2147 assert_eq!(parse("$self"), "$[$%:Block,$[$%:SelfObj]]");
2148 assert_eq!(parse("$d"), "$[$%:Block,$[$%:SelfData]]");
2149 assert_eq!(parse("$data"), "$[$%:Block,$[$%:SelfData]]");
2150 }
2151
2152 #[test]
2153 fn check_backtick_ident() {
2154 assert_eq!(parse("` `"), "$[$%:Block,$[$%:Var,:\" \"]]");
2155 assert_eq!(parse("`\\``"), "$[$%:Block,$[$%:Var,:\"`\"]]");
2156 assert_eq!(parse("`\\\"`"), "$[$%:Block,$[$%:Var,:\"\"\"]]");
2157 assert_eq!(parse("`\"`"), "$[$%:Block,$[$%:Var,:\"\"\"]]");
2158 assert_eq!(parse("!` ` = 10;"), "$[$%:Block,$[$%:Def,$[:\" \"],10]]");
2159 }
2160
2161 #[test]
2162 fn check_apply() {
2163 assert_eq!(parse("fo[[@]]"), "$[$%:Block,$[$%:Apply,$[$%:Var,:fo],$[$%:Var,:@]]]");
2164 assert_eq!(parse("fo[[$[1,2,3]]]"), "$[$%:Block,$[$%:Apply,$[$%:Var,:fo],$[$%:Lst,1,2,3]]]");
2165 assert_eq!(parse("obj.1.field[[_]]"), "$[$%:Block,$[$%:Apply,$[$%:GetSym,$[$%:GetIdx,$[$%:Var,:obj],1],:field],$[$%:Var,:_]]]");
2166 assert_eq!(parse("obj.1.(\"field\")[[_]]"), "$[$%:Block,$[$%:Apply,$[$%:GetSym,$[$%:GetIdx,$[$%:Var,:obj],1],\"field\"],$[$%:Var,:_]]]");
2167 }
2168
2169 #[test]
2170 fn check_right_call() {
2171 assert_eq!(parse("10 |> 20"), "$[$%:Block,$[$%:Call,10,20]]");
2172 assert_eq!(parse("10 20"), "$[$%:Block,$[$%:Call,10,20]]");
2173 assert_eq!(parse("10 |> 20 |> 30"), "$[$%:Block,$[$%:Call,$[$%:Call,10,20],30]]");
2174 assert_eq!(parse("10 20 |> 30"), "$[$%:Block,$[$%:Call,$[$%:Call,10,20],30]]");
2175
2176 assert_eq!(parse("10 20 |> 20 30 40"), "$[$%:Block,$[$%:Call,$[$%:Call,10,20],$[$%:Call,20,30,40]]]");
2177
2178 assert_eq!(parse("10 11 |> 20"), "$[$%:Block,$[$%:Call,$[$%:Call,10,11],20]]");
2179 assert_eq!(parse("10 11 |> 20 |> 30"), "$[$%:Block,$[$%:Call,$[$%:Call,$[$%:Call,10,11],20],30]]");
2180 assert_eq!(parse("10 11 |> 20 21 |> 30"), "$[$%:Block,$[$%:Call,$[$%:Call,$[$%:Call,10,11],$[$%:Call,20,21]],30]]");
2181 assert_eq!(parse("10 11 |> 20 21 |> 30 31"), "$[$%:Block,$[$%:Call,$[$%:Call,$[$%:Call,10,11],$[$%:Call,20,21]],$[$%:Call,30,31]]]");
2182 }
2183
2184 #[test]
2185 fn check_const() {
2186 assert_eq!(parse("!:const X = 32;"), "$[$%:Block,$[$%:DefConst,$[:X],32]]");
2187 assert_eq!(parse("!:const X = 32.4;"), "$[$%:Block,$[$%:DefConst,$[:X],32.4]]");
2188 assert_eq!(parse("!:const X = :XX;"), "$[$%:Block,$[$%:DefConst,$[:X],$[$%:Key,:XX]]]");
2189 assert_eq!(parse("!:const X = \"fo\";"), "$[$%:Block,$[$%:DefConst,$[:X],$[$%:Str,\"fo\"]]]");
2190 assert_eq!(parse("!:const X = $[120];"), "$[$%:Block,$[$%:DefConst,$[:X],$[$%:Lst,120]]]");
2191 assert_eq!(parse("!:const X = ${a=10};"), "$[$%:Block,$[$%:DefConst,$[:X],$[$%:Map,$[:a,10]]]]");
2192 assert_eq!(parse("!:const (A,B,X) = $[1,3,4];"), "$[$%:Block,$[$%:DefConst,$[:A,:B,:X],$[$%:Lst,1,3,4],$true]]");
2193 }
2194
2195 #[test]
2196 fn check_indent_error() {
2197 assert_eq!(parse_error(" 10 11\n12"),
2198 "Parse error: <parser_test>:2:1 Call argument does not belong to call, it needs a higher indentation.\nat code:\n2 | 12\n");
2199 assert_eq!(parse_error("10 11\n12"),
2200 "Parse error: <parser_test>:2:1 Call argument does not belong to call, it needs a higher indentation.\nat code:\n2 | 12\n");
2201 assert_eq!(parse_error("!x = 10 11\n12"),
2202 "Parse error: <parser_test>:2:1 Call argument does not belong to call, it needs a higher indentation.\nat code:\n2 | 12\n");
2203 assert_eq!(parse("10 11\n 12"),
2204 "$[$%:Block,$[$%:Call,10,11,12]]");
2205 assert_eq!(parse("10 11\n;12"),
2206 "$[$%:Block,$[$%:Call,10,11],12]");
2207 assert_eq!(parse("10 11\n;\n12"),
2208 "$[$%:Block,$[$%:Call,10,11],12]");
2209 assert_eq!(parse("10 11\n 12 13"),
2210 "$[$%:Block,$[$%:Call,10,11,12,13]]");
2211 assert_eq!(parse("!x = 10 11\n 12"),
2212 "$[$%:Block,$[$%:Def,$[:x],$[$%:Call,10,11,12]]]");
2213 assert_eq!(parse("!x = 10 11\n 12 13"),
2214 "$[$%:Block,$[$%:Def,$[:x],$[$%:Call,10,11,12,13]]]");
2215 }
2216
2217 #[test]
2218 fn check_nvec() {
2219 assert_eq!(parse("$i(30, 18, 5)"), "$[$%:Block,$[$%:IVec,30,18,5]]");
2220 assert_eq!(parse("$i(30,18,5)"), "$[$%:Block,$[$%:IVec,30,18,5]]");
2221 assert_eq!(parse("$i(0b100,0xC,0o10)"), "$[$%:Block,$[$%:IVec,4,12,8]]");
2222 assert_eq!(parse("$i(0b101 + 1, 0xF * 4)"), "$[$%:Block,$[$%:IVec,$[$%:BinOpAdd,5,1],$[$%:BinOpMul,15,4]]]");
2223 assert_eq!(parse("$f(1.2, 3.4, 5.6, 7.8)"), "$[$%:Block,$[$%:FVec,1.2,3.4,5.6,7.8]]");
2225 assert_eq!(
2226 parse("$f(1/2, 1/3, 1/4, 1/5)"),
2227 "$[$%:Block,$[$%:FVec,$[$%:BinOpDiv,1,2],$[$%:BinOpDiv,1,3],$[$%:BinOpDiv,1,4],$[$%:BinOpDiv,1,5]]]"
2228 );
2229 }
2230
2231 #[test]
2232 fn check_pair_op() {
2233 assert_eq!(parse("match x a => b x => d 5"), "$[$%:Block,$[$%:Call,$[$%:Var,:match],$[$%:Var,:x],$p($[$%:Var,:a],$[$%:Var,:b]),$p($[$%:Var,:x],$[$%:Var,:d]),5]]");
2234 assert_eq!(parse("iter i 0 => 10 ~ 20"), "$[$%:Block,$[$%:Call,$[$%:Var,:iter],$[$%:Var,:i],$p(0,10),20]]");
2235 assert_eq!(parse("iter i 0 => 10 \\20"), "$[$%:Block,$[$%:Call,$[$%:Var,:iter],$[$%:Var,:i],$p(0,10),$[$%:Func,$n,$n,20]]]");
2236 assert_eq!(parse("iter i 0 => 10 { 20 }"), "$[$%:Block,$[$%:Call,$[$%:Var,:iter],$[$%:Var,:i],$p(0,10),$[$%:Func,$n,$n,20]]]");
2237 }
2238
2239 #[test]
2240 fn check_call_op() {
2241 assert_eq!(parse("a &> b x"), "$[$%:Block,$[$%:Call,$[$%:Call,$[$%:Var,:b],$[$%:Var,:a]],$[$%:Var,:x]]]");
2242 assert_eq!(parse("x a &> b"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Var,:b],$[$%:Var,:a]]]]");
2243 assert_eq!(parse("x a &> b &> c"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Var,:c],$[$%:Call,$[$%:Var,:b],$[$%:Var,:a]]]]]");
2244 assert_eq!(parse("x a &> b <& c"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Call,$[$%:Var,:b],$[$%:Var,:a]],$[$%:Var,:c]]]]");
2245 assert_eq!(parse("x a <& b"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Var,:a],$[$%:Var,:b]]]]");
2246 assert_eq!(parse("x a <& b <& c"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Var,:a],$[$%:Call,$[$%:Var,:b],$[$%:Var,:c]]]]]");
2247 assert_eq!(parse("x a <& b &> c"), "$[$%:Block,$[$%:Call,$[$%:Var,:x],$[$%:Call,$[$%:Var,:a],$[$%:Call,$[$%:Var,:c],$[$%:Var,:b]]]]]");
2248 }
2249
2250 #[test]
2251 fn check_coll_add_op() {
2252 assert_eq!(parse("${} +> k => v"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Map],$p($[$%:Var,:k],$[$%:Var,:v])]]");
2253 assert_eq!(parse("${} +> (k => v) +> k2 => v2"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Map],$p($[$%:Var,:k],$[$%:Var,:v]),$p($[$%:Var,:k2],$[$%:Var,:v2])]]");
2254 assert_eq!(parse("${} +> k => v +> k2 => v2"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Map],$p($[$%:Var,:k],$[$%:Var,:v]),$p($[$%:Var,:k2],$[$%:Var,:v2])]]");
2255 assert_eq!(parse("k3 => v3 <+ k2 => v2 <+ k => v <+ ${}"), "$[$%:Block,$[$%:Call,$%:OpColAddL,$[$%:Map],$p($[$%:Var,:k],$[$%:Var,:v]),$p($[$%:Var,:k2],$[$%:Var,:v2]),$p($[$%:Var,:k3],$[$%:Var,:v3])]]");
2256 assert_eq!(parse("${} +> :a => 10 +> 4 + 3 => 20 * 2 +> :x"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Map],$p($[$%:Key,:a],10),$p($[$%:BinOpAdd,4,3],$[$%:BinOpMul,20,2]),$[$%:Key,:x]]]");
2257 assert_eq!(parse("${} +> :a => 10 +> :b => 20 * 2 +> :x"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Map],$p($[$%:Key,:a],10),$p($[$%:Key,:b],$[$%:BinOpMul,20,2]),$[$%:Key,:x]]]");
2258
2259 assert_eq!(parse("a +> b +> c"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Var,:a],$[$%:Var,:b],$[$%:Var,:c]]]");
2260 assert_eq!(parse("c <+ b <+ a"), "$[$%:Block,$[$%:Call,$%:OpColAddL,$[$%:Var,:a],$[$%:Var,:b],$[$%:Var,:c]]]");
2261 assert_eq!(parse("a +> b"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:Var,:a],$[$%:Var,:b]]]");
2262 assert_eq!(parse("b <+ a"), "$[$%:Block,$[$%:Call,$%:OpColAddL,$[$%:Var,:a],$[$%:Var,:b]]]");
2263
2264 assert_eq!(parse("a + x +> b + x"), "$[$%:Block,$[$%:Call,$%:OpColAddR,$[$%:BinOpAdd,$[$%:Var,:a],$[$%:Var,:x]],$[$%:BinOpAdd,$[$%:Var,:b],$[$%:Var,:x]]]]");
2265 assert_eq!(parse("a + c <+ b + c"), "$[$%:Block,$[$%:Call,$%:OpColAddL,$[$%:BinOpAdd,$[$%:Var,:b],$[$%:Var,:c]],$[$%:BinOpAdd,$[$%:Var,:a],$[$%:Var,:c]]]]");
2266
2267 }
2268
2269 #[test]
2270 fn check_char() {
2271 assert_eq!(parse("'f'"), "$[$%:Block,\'f\']");
2272 assert_eq!(parse("'\\xFF'"), "$[$%:Block,\'ÿ\']");
2273 assert_eq!(parse("$b'f'"), "$[$%:Block,$b\'f\']");
2274 assert_eq!(parse("$b'\\xFF'"), "$[$%:Block,$b\'\\xFF\']");
2275
2276 assert_eq!(parse("'\\u{3132}'"), "$[$%:Block,\'ㄲ\']");
2277 assert_eq!(parse("'\\u{FF}'"), "$[$%:Block,\'ÿ\']");
2278 assert_eq!(parse("$b'\\u{3132}'"), "$[$%:Block,$b\'?\']");
2279 assert_eq!(parse("$b'\\u{FF}'"), "$[$%:Block,$b\'\\xFF\']");
2280 }
2281}