wlambda/
parser.rs

1// Copyright (c) 2020-2022 Weird Constructor <weirdconstructor@gmail.com>
2// This is a part of WLambda. See README.md and COPYING for details.
3#![allow(clippy::collapsible_if)]
4
5/*!
6This is the grammar parser for WLambda.
7
8It produces an AST to be further
9transformed by `wlambda::compiler::compile()` into an executable form
10of the program.
11
12The parser is a bit crufty as I did not go the extra step of writing
13a lexer/tokenizer. One goal of WLambda is to have a rather uncomplicated
14and small implementation, and I hope I could achieve that here.
15
16The syntax of WLambda is in part also to make it a bit easier
17to parse in this hand written parser.
18
19*/
20
21
22use 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
32/// Helper function for recording characters into a byte buffer.
33fn 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
44/// Helper function for recording a string character either
45/// as byte for a byte buffer in `v` or as character for a `String` `s`.
46fn 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
51/// Parses a quoted byte vector or string.
52fn 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
66/// Parsers a WLambda special quoted part of code.
67fn 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
104/// Parses the part of a numerical vector that comes after the declaration,
105/// in `$i(1, 2, 3)` `$i` is the declaration.
106fn 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            // how many dimensions are in the numerical vector we just parsed?
121            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
283/// Parses a WLambda character or byte
284fn 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
338/// Parsers a WLambda string or byte buffer.
339fn 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    //println!("parse_map [{}]", ps.rest());
496    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    //println!("parse_value [{}]", ps.rest());
1020    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(); // consume '=' too!
1206
1207                    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 if right.v_(0).get_syn() == Syntax::OpColAddR {
1388//                binop.push(left);
1389//                for (v, _) in right.iter().skip(1) {
1390//                    binop.push(v);
1391//                }
1392//                binop
1393            } 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    //println!("parse_expr [{}] np={}", ps.rest(), no_pipe);
1433    let call_indent = ps.indent_pos();
1434    //d// println!("CALL INDENT: {:?} @'{}'", call_indent, ps.rest());
1435    let mut value = parse_value(ps)?;
1436
1437    // look ahead, if we see an expression delimiter.
1438    // because then, this is not going to be a call!
1439    // Also exception to parse_expr, we are excluding the '|'.
1440    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                // We don't set value here, because it will not be
1468                // used by '(' or '.' cases anymore!
1469                // Those will be covered by parse_expr() presumably.
1470                return Ok(res_call);
1471            },
1472            ';' | ')' | ',' | ']' | '|' | '}' => {
1473                break;
1474            },
1475            _ if op.is_some() => {
1476                if binop_mode { break; }
1477
1478//                let op        = op.unwrap();
1479//                let binop     = make_binop(ps, op);
1480//                let (_, r_bp) = get_op_binding_power(op);
1481//
1482//                let op_len = op.len();
1483//                ps.consume_wsc_n(op_len);
1484
1485                // TODO: Need to fix the pratt parser to properly handle
1486                //       the binding power of the first op here.
1487                //       There is missing a loop here.
1488                // https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
1489                value = reform_binop(parse_binop(Some(value), ps, 0)?);
1490            },
1491            '=' => { break; }, // '=' from parsing map keys
1492            _ => {
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                //d// println!("INDENT: {:?} VS {:?} '{}'", ps.indent_pos(), call_indent, ps.rest());
1499                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(); // consume '=' too!
1632
1633        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    //println!("parse_stmt [{}]", ps.rest());
1666    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
1727/// Parses an arity definition for a function.
1728fn 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
1771/// This function parses the an optionally delimited block of WLambda statements.
1772///
1773/// If _with_arity_ is set, the arity declaration `|a<b|` is parsed.
1774/// If _delimited_ is set, "{" and "}" are expected at the end/beginning of a block.
1775/// If _end_delim_ is set, the parsing loop for the statement ends when a "}"
1776/// is encountered.
1777///
1778/// ```rust
1779/// use wlambda::parser::{State, parse_block};
1780///
1781/// let code = "!a = 0; !b = 1; a + b";
1782/// let mut ps = State::new(&code, "somefilename");
1783///
1784/// // Parse a bare block without '{' ... '}' delimiters:
1785/// match parse_block(&mut ps, false, false, false) {
1786///     Ok(v)  => { println!("Result: {}", v.s()); },
1787///     Err(e) => { panic!("ERROR: {}", e); },
1788/// }
1789/// ```
1790///
1791/// The return value is a abstract syntax tree in a VVal data structure
1792/// that is ready for the `compiler` to be compiled. It consists mostly of
1793/// `VVal::Lst` and `VVal::Syn` nodes. The latter hold the position information
1794/// of the AST nodes.
1795pub 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
1841/// Facade function for an undelimited `parse_block`.
1842///
1843/// ```rust
1844/// use wlambda::parser::parse;
1845///
1846/// match parse("123; 456", "filenamehere") {
1847///     Ok(ast)  => println!("AST: {}", ast.s()),
1848///     Err(e) => { panic!("ERROR: {}", e); },
1849/// }
1850/// ```
1851pub 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("$i(0b100+2,0xC*4)"),          "$[$%:Block,$[$%:IVec,$[$%:BinOpAdd,4,2],$[$%:BinOpMul,12,4]]]");
2224        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}