ucglib/parse/
mod.rs

1// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
2//
3//  Licensed under the Apache License, Version 2.0 (the "License");
4//  you may not use this file except in compliance with the License.
5//  You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14
15//! The Parsing stage of the ucg compiler.
16use std;
17use std::borrow::Borrow;
18use std::str::FromStr;
19
20use abortable_parser;
21use abortable_parser::combinators::eoi;
22use abortable_parser::iter::SliceIter;
23use abortable_parser::{Error, Peekable, Result};
24
25use self::precedence::op_expression;
26use crate::ast::*;
27use crate::error::BuildError;
28use crate::iter::OffsetStrIter;
29use crate::tokenizer::*;
30
31pub use crate::tokenizer::{CommentGroup, CommentMap};
32
33type ParseResult<'a, O> = Result<SliceIter<'a, Token>, O>;
34
35#[cfg(feature = "tracing")]
36const ENABLE_TRACE: bool = true;
37#[cfg(not(feature = "tracing"))]
38const ENABLE_TRACE: bool = false;
39
40type ConvertResult<'a, O> = std::result::Result<O, abortable_parser::Error<SliceIter<'a, Token>>>;
41
42macro_rules! trace_parse {
43    ($i:expr, $rule:ident!( $($args:tt)* )) => {
44        {
45            use crate::parse::ENABLE_TRACE;
46            if ENABLE_TRACE {
47                eprintln!("Entering Rule: {:?} {:?}", stringify!($rule), $i);
48            }
49            let result = $rule!($i, $($args)* );
50            if ENABLE_TRACE {
51                eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
52            }
53            result
54        }
55    };
56
57    ($i:expr, $rule:ident) => {
58        {
59            use crate::parse::ENABLE_TRACE;
60            if ENABLE_TRACE {
61                eprintln!("Entering Rule: {:?} {:?}", stringify!($rule), $i);
62            }
63            let result = run!($i, $rule);
64            if ENABLE_TRACE {
65                eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
66            }
67            result
68        }
69    };
70}
71
72fn symbol_to_value(s: &Token) -> ConvertResult<Value> {
73    Ok(Value::Symbol(value_node!(
74        s.fragment.to_string(),
75        s.pos.clone()
76    )))
77}
78
79// symbol is a bare unquoted field.
80make_fn!(
81    symbol<SliceIter<Token>, Value>,
82    match_type!(BAREWORD => symbol_to_value)
83);
84
85fn str_to_value(s: &Token) -> ConvertResult<Value> {
86    Ok(Value::Str(value_node!(
87        s.fragment.to_string(),
88        s.pos.clone()
89    )))
90}
91
92// quoted_value is a quoted string.
93make_fn!(
94    quoted_value<SliceIter<Token>, Value>,
95    match_type!(STR => str_to_value)
96);
97
98// Helper function to make the return types work for down below.
99fn triple_to_number<'a>(
100    input: SliceIter<'a, Token>,
101    v: (Option<Token>, Option<Token>, Option<Token>),
102) -> ConvertResult<'a, Value> {
103    let (pref, mut pref_pos) = match v.0 {
104        None => ("", Position::new(0, 0, 0)),
105        Some(ref bs) => (bs.fragment.borrow(), bs.pos.clone()),
106    };
107
108    let has_dot = v.1.is_some();
109
110    if v.0.is_some() && !has_dot && v.2.is_none() {
111        let i = match FromStr::from_str(pref) {
112            Ok(i) => i,
113            Err(_) => {
114                return Err(Error::new(
115                    format!("Not an integer! {}", pref),
116                    Box::new(input.clone()),
117                ));
118            }
119        };
120        return Ok(Value::Int(value_node!(i, pref_pos)));
121    }
122
123    if v.0.is_none() && has_dot {
124        pref_pos = v.1.unwrap().pos;
125    }
126
127    let suf = match v.2 {
128        None => "".to_string(),
129        Some(bs) => bs.fragment,
130    };
131
132    let to_parse = pref.to_string() + "." + &suf;
133    let f = match FromStr::from_str(&to_parse) {
134        Ok(f) => f,
135        Err(_) => {
136            return Err(Error::new(
137                format!("Not a float! {}", to_parse),
138                Box::new(input.clone()),
139            ));
140        }
141    };
142    return Ok(Value::Float(value_node!(f, pref_pos)));
143}
144
145// trace_macros!(true);
146
147// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
148// alot. We need to process alternatives in order of decreasing
149// specificity.  Unfortunately this means we are required to go in a
150// decreasing size order which messes with either!'s completion logic. To
151// work around this we have to force Incomplete to be Error so that
152// either! will try the next in the series instead of aborting.
153//
154// *IMPORTANT*
155// It also means this combinator is risky when used with partial
156// inputs. So handle with care.
157fn number(input: SliceIter<Token>) -> Result<SliceIter<Token>, Value> {
158    let parsed = do_each!(input,
159         num => either!(
160             complete!(
161                  "Not a float",
162                  do_each!( // 1.0
163                      prefix => match_type!(DIGIT),
164                      has_dot => punct!("."),
165                      suffix => match_type!(DIGIT),
166                      (Some(prefix.clone()), Some(has_dot.clone()), Some(suffix.clone()))
167             )),
168             complete!(
169                  "Not a float",
170                  do_each!( // 1.
171                      prefix => match_type!(DIGIT),
172                      has_dot => punct!("."),
173                      (Some(prefix.clone()), Some(has_dot.clone()), None)
174             )),
175             complete!(
176                  "Not a float",
177                  do_each!( // .1
178                      has_dot => punct!("."),
179                      suffix => match_type!(DIGIT),
180                      (None, Some(has_dot.clone()), Some(suffix.clone()))
181             )),
182             do_each!( // 1
183                 prefix => match_type!(DIGIT),
184                 (Some(prefix.clone()), None, None)
185             )),
186         (num)
187    );
188    match parsed {
189        Result::Abort(e) => Result::Abort(e),
190        Result::Fail(e) => Result::Fail(e),
191        Result::Incomplete(offset) => Result::Incomplete(offset),
192        Result::Complete(rest, triple) => {
193            let num = triple_to_number(rest.clone(), triple);
194            match num {
195                Ok(val) => Result::Complete(rest, val),
196                Err(e) => Result::Fail(e),
197            }
198        }
199    }
200}
201// trace_macros!(false);
202
203make_fn!(
204    boolean_value<SliceIter<Token>, Value>,
205    do_each!(
206        b => match_type!(BOOLEAN),
207        (Value::Boolean(PositionedItem{
208            val: b.fragment == "true",
209            pos: b.pos,
210        }))
211    )
212);
213
214make_fn!(
215    field_value<SliceIter<Token>, (Token, Expression)>,
216    do_each!(
217            field => wrap_err!(either!(match_type!(BOOLEAN), match_type!(BAREWORD), match_type!(STR)),
218                               "Field names must be a bareword or a string."),
219            _ => optional!(shape_suffix),
220            _ => must!(punct!("=")),
221            value => must!(expression),
222            (field, value)
223    )
224);
225
226// Helper function to make the return types work for down below.
227fn vec_to_tuple(pos: Position, fields: Option<FieldList>) -> Value {
228    Value::Tuple(value_node!(fields.unwrap_or(Vec::new()), pos))
229}
230
231make_fn!(
232    field_list<SliceIter<Token>, FieldList>,
233    separated!(punct!(","), field_value)
234);
235
236make_fn!(
237    tuple<SliceIter<Token>, Value>,
238    do_each!(
239        pos => pos,
240        _ => punct!("{"),
241        v => optional!(field_list),
242        _ => optional!(punct!(",")),
243        _ => must!(punct!("}")),
244        (vec_to_tuple(pos, v))
245    )
246);
247
248fn tuple_to_list<Sp: Into<Position>>(pos: Sp, elems: Option<Vec<Expression>>) -> Value {
249    Value::List(ListDef {
250        elems: elems.unwrap_or_else(|| Vec::new()),
251        pos: pos.into(),
252    })
253}
254
255make_fn!(
256    list_value<SliceIter<Token>, Value>,
257    do_each!(
258        start => punct!("["),
259        elements => optional!(separated!(punct!(","), expression)),
260        _ => optional!(punct!(",")),
261        _ => must!(punct!("]")),
262        (tuple_to_list(start.pos, elements))
263    )
264);
265
266make_fn!(
267    empty_value<SliceIter<Token>, Value>,
268    do_each!(
269        pos => pos,
270        _ => match_type!(EMPTY),
271        (Value::Empty(pos.into()))
272    )
273);
274
275make_fn!(
276    compound_value<SliceIter<Token>, Value>,
277    either!(trace_parse!(list_value), trace_parse!(tuple))
278);
279
280make_fn!(
281    value<SliceIter<Token>, Value>,
282    either!(
283        trace_parse!(symbol),
284        trace_parse!(compound_value),
285        trace_parse!(boolean_value),
286        trace_parse!(empty_value),
287        trace_parse!(number),
288        trace_parse!(quoted_value)
289    )
290);
291
292make_fn!(
293    shape_suffix<SliceIter<Token>, Value>,
294    do_each!(
295        _ => punct!("::"),
296        shape => value,
297        (dbg!(shape))
298    )
299);
300
301fn value_to_expression(v: Value) -> Expression {
302    Expression::Simple(v)
303}
304
305make_fn!(
306    simple_expression<SliceIter<Token>, Expression>,
307    do_each!(
308        val => trace_parse!(value),
309        _ => not!(either!(punct!("{"), punct!("["), punct!("("))),
310        (value_to_expression(val))
311    )
312);
313
314fn expression_to_grouped_expression(e: Expression, pos: Position) -> Expression {
315    Expression::Grouped(Box::new(e), pos)
316}
317
318make_fn!(
319    grouped_expression<SliceIter<Token>, Expression>,
320    do_each!(
321        pos => pos,
322        _ => punct!("("),
323        expr => do_each!(
324            expr => trace_parse!(expression),
325            _ => must!(punct!(")")),
326            (expr)
327        ),
328        (expression_to_grouped_expression(expr, pos))
329    )
330);
331
332fn tuple_to_copy(sym: Value, fields: Option<FieldList>) -> Expression {
333    let pos = sym.pos().clone();
334    let fields = match fields {
335        Some(fields) => fields,
336        None => Vec::new(),
337    };
338    Expression::Copy(CopyDef {
339        selector: sym,
340        fields: fields,
341        pos: pos,
342    })
343}
344
345make_fn!(
346    copy_expression<SliceIter<Token>, Expression>,
347    do_each!(
348        sym => trace_parse!(symbol),
349        _ => punct!("{"),
350        fields => optional!(trace_parse!(field_list)),
351        _ => optional!(punct!(",")),
352        _ => must!(punct!("}")),
353        (tuple_to_copy(sym, fields))
354    )
355);
356
357fn tuple_to_func<'a>(
358    pos: Position,
359    vals: Option<Vec<Value>>,
360    val: Expression,
361) -> ConvertResult<'a, Expression> {
362    let mut default_args = match vals {
363        None => Vec::new(),
364        Some(vals) => vals,
365    };
366    let arglist = default_args
367        .drain(0..)
368        .map(|s| PositionedItem {
369            pos: s.pos().clone(),
370            val: s.to_string(),
371        })
372        .collect();
373    Ok(Expression::Func(FuncDef {
374        scope: None,
375        argdefs: arglist,
376        fields: Box::new(val),
377        pos: pos,
378    }))
379}
380
381make_fn!(
382    arglist<SliceIter<Token>, Vec<Value>>,
383    separated!(
384        punct!(","),
385        do_each!(
386            sym => symbol,
387            _ => optional!(shape_suffix),
388            (sym)
389        )
390    )
391);
392
393fn module_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
394    let parsed = do_each!(input,
395        pos => pos,
396        _ => word!("module"),
397        _ => must!(punct!("{")),
398        arglist => trace_parse!(optional!(field_list)),
399        _ => optional!(punct!(",")),
400        _ => must!(punct!("}")),
401        _ => must!(punct!("=>")),
402        out_expr => optional!(
403            do_each!(
404                _ => punct!("("),
405                expr => must!(do_each!(
406                        expr => expression,
407                        _ => optional!(shape_suffix),
408                        (expr)
409                    )
410                ),
411                _ => must!(punct!(")")),
412                (expr)
413            )
414        ),
415        _ => must!(punct!("{")),
416        stmt_list =>  trace_parse!(repeat!(statement)),
417        _ => must!(punct!("}")),
418        (pos, arglist, out_expr, stmt_list)
419    );
420    match parsed {
421        Result::Abort(e) => Result::Abort(e),
422        Result::Fail(e) => Result::Fail(e),
423        Result::Incomplete(offset) => Result::Incomplete(offset),
424        Result::Complete(rest, (pos, arglist, out_expr, stmt_list)) => {
425            let mut def = ModuleDef::new(arglist.unwrap_or_else(|| Vec::new()), stmt_list, pos);
426            if let Some(expr) = out_expr {
427                def.set_out_expr(expr);
428            }
429            Result::Complete(rest, Expression::Module(def))
430        }
431    }
432}
433
434fn func_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
435    let parsed = do_each!(input,
436        pos => pos,
437        _ => word!("func"),
438        _ => must!(punct!("(")),
439        arglist => trace_parse!(optional!(arglist)),
440        _ => must!(punct!(")")),
441        _ => must!(punct!("=>")),
442        map =>  trace_parse!(expression),
443        (pos, arglist, map)
444    );
445    match parsed {
446        Result::Abort(e) => Result::Abort(e),
447        Result::Fail(e) => Result::Fail(e),
448        Result::Incomplete(offset) => Result::Incomplete(offset),
449        Result::Complete(rest, (pos, arglist, map)) => match tuple_to_func(pos, arglist, map) {
450            Ok(expr) => Result::Complete(rest, expr),
451            Err(e) => Result::Fail(Error::caused_by(
452                "Invalid func syntax",
453                Box::new(e),
454                Box::new(rest.clone()),
455            )),
456        },
457    }
458}
459
460make_fn!(
461    alt_select_expression<SliceIter<Token>, Expression>,
462    do_each!(
463        pos => pos,
464        _ => word!("select"),
465        _ => must!(punct!("(")),
466        val => must!(expression),
467        default => optional!(
468            do_each!(
469                _ => punct!(","),
470                def => must!(expression),
471                (def)
472            )
473        ),
474        _ => optional!(punct!(",")),
475        _ => must!(punct!(")")),
476        _ => must!(punct!("=>")),
477        _ => must!(punct!("{")),
478        tpl => must!(field_list),
479        _ => optional!(punct!(",")),
480        _ => must!(punct!("}")),
481        (Expression::Select(SelectDef {
482            val: Box::new(val),
483            default: default.map(|e| Box::new(e)),
484            tuple: tpl,
485            pos: pos,
486        }))
487    )
488);
489
490make_fn!(
491    simple_format_args<SliceIter<Token>, FormatArgs>,
492    do_each!(
493        _ => punct!("("),
494        args => separated!(punct!(","), trace_parse!(expression)),
495        _ => must!(punct!(")")),
496        (FormatArgs::List(args))
497    )
498);
499
500make_fn!(
501    expression_format_args<SliceIter<Token>, FormatArgs>,
502    do_each!(
503        expr => must!(expression),
504        (FormatArgs::Single(Box::new(expr)))
505    )
506);
507
508make_fn!(
509    format_expression<SliceIter<Token>, Expression>,
510    do_each!(
511        tmpl => match_type!(STR),
512        _ => punct!("%"),
513        args => wrap_err!(must!(either!(simple_format_args, expression_format_args)),
514            "Expected format arguments"),
515        (Expression::Format(FormatDef {
516            template: tmpl.fragment.to_string(),
517            args: args,
518            pos: tmpl.pos,
519        }))
520    )
521);
522
523make_fn!(
524    include_expression<SliceIter<Token>, Expression>,
525    do_each!(
526        pos => pos,
527        _ => word!("include"),
528        typ => must!(match_type!(BAREWORD)),
529        path => must!(match_type!(STR)),
530        (Expression::Include(IncludeDef{
531            pos: pos,
532            typ: typ,
533            path: path,
534        }))
535    )
536);
537
538fn tuple_to_call<'a>(
539    input: SliceIter<'a, Token>,
540    val: Value,
541    exprs: Option<Vec<Expression>>,
542) -> ConvertResult<'a, Expression> {
543    if let Value::Symbol(_) = val {
544        Ok(Expression::Call(CallDef {
545            funcref: val,
546            arglist: exprs.unwrap_or_else(|| Vec::new()),
547            pos: (&input).into(),
548        }))
549    } else {
550        Err(Error::new(
551            format!("Expected Selector Got {:?}", val),
552            Box::new(input.clone()),
553        ))
554    }
555}
556
557make_fn!(
558    cast_expression<SliceIter<Token>, Expression>,
559    do_each!(
560        typ => either!(
561            word!("int"),
562            word!("float"),
563            word!("str"),
564            word!("bool")
565        ),
566        _ => punct!("("),
567        expr => expression,
568        _ => punct!(")"),
569        (Expression::Cast(CastDef{
570            cast_type: match typ.fragment.as_str() {
571                "int" => CastType::Int,
572                "float" => CastType::Float,
573                "str" => CastType::Str,
574                "bool" => CastType::Bool,
575                _ => unreachable!(),
576            },
577            target: Box::new(expr),
578            pos: typ.pos,
579        }))
580    )
581);
582
583fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
584    let parsed = do_each!(input.clone(),
585        callee_name => trace_parse!(symbol),
586        _ => punct!("("),
587        args => optional!(separated!(punct!(","), trace_parse!(expression))),
588        _ => optional!(punct!(",")),
589        _ => must!(punct!(")")),
590        (callee_name, args)
591    );
592    match parsed {
593        Result::Abort(e) => Result::Abort(e),
594        Result::Fail(e) => Result::Fail(e),
595        Result::Incomplete(offset) => Result::Incomplete(offset),
596        Result::Complete(rest, (name, args)) => match tuple_to_call(input.clone(), name, args) {
597            Ok(expr) => Result::Complete(rest, expr),
598            Err(e) => Result::Fail(Error::caused_by(
599                "Invalid Call Syntax",
600                Box::new(e),
601                Box::new(rest),
602            )),
603        },
604    }
605}
606
607make_fn!(
608    reduce_expression<SliceIter<Token>, Expression>,
609    do_each!(
610        pos => pos,
611        _ => word!("reduce"),
612        _ => must!(punct!("(")),
613        func => must!(expression),
614        _ => must!(punct!(",")),
615        acc => must!(trace_parse!(expression)),
616        _ => must!(punct!(",")),
617        tgt => must!(trace_parse!(expression)),
618        _ => optional!(punct!(",")),
619        _ => must!(punct!(")")),
620        (Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{
621            func: Box::new(func),
622            acc: Box::new(acc),
623            target: Box::new(tgt),
624            pos: pos,
625        })))
626    )
627);
628
629make_fn!(
630    map_expression<SliceIter<Token>, Expression>,
631    do_each!(
632        pos => pos,
633        _ => word!("map"),
634        _ => must!(punct!("(")),
635        func => must!(expression),
636        _ => must!(punct!(",")),
637        list => must!(trace_parse!(expression)),
638        _ => optional!(punct!(",")),
639        _ => must!(punct!(")")),
640        (Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{
641            func: Box::new(func),
642            target: Box::new(list),
643            pos: pos,
644        })))
645    )
646);
647
648make_fn!(
649    filter_expression<SliceIter<Token>, Expression>,
650    do_each!(
651        pos => pos,
652        _ => word!("filter"),
653        _ => must!(punct!("(")),
654        func => must!(expression),
655        _ => must!(punct!(",")),
656        list => must!(trace_parse!(expression)),
657        _ => optional!(punct!(",")),
658        _ => must!(punct!(")")),
659        (Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{
660            func: Box::new(func),
661            target: Box::new(list),
662            pos: pos,
663        })))
664    )
665);
666
667make_fn!(
668    func_op_expression<SliceIter<Token>, Expression>,
669    either!(reduce_expression, map_expression, filter_expression)
670);
671
672make_fn!(
673    range_expression<SliceIter<Token>, Expression>,
674    do_each!(
675        pos => pos,
676        start => either!(simple_expression, grouped_expression),
677        _ => punct!(":"),
678        maybe_step => optional!(
679            do_each!(
680                step => either!(simple_expression, grouped_expression),
681                _ => punct!(":"),
682                (Box::new(step))
683            )
684        ),
685        end => must!(wrap_err!(either!(simple_expression, grouped_expression), "Expected simple or grouped expression")),
686        (Expression::Range(RangeDef{
687            pos: pos,
688            start: Box::new(start),
689            step: maybe_step,
690            end: Box::new(end),
691        }))
692    )
693);
694
695make_fn!(
696    import_expression<SliceIter<Token>, Expression>,
697    do_each!(
698        pos => pos,
699        _ => word!("import"),
700        path => must!(wrap_err!(match_type!(STR), "Expected import path")),
701        (Expression::Import(ImportDef{
702            pos: pos,
703            path: path,
704        }))
705    )
706);
707
708make_fn!(
709    string_expression<SliceIter<Token>, Expression>,
710    do_each!(
711        val => trace_parse!(quoted_value),
712        (value_to_expression(val))
713    )
714);
715
716make_fn!(
717    fail_expression<SliceIter<Token>, Expression>,
718    do_each!(
719        pos => pos,
720        _ => word!("fail"),
721        msg => must!(wrap_err!(expression, "Expected failure message")),
722        (Expression::Fail(FailDef{
723            pos: pos,
724            message: Box::new(msg),
725        }))
726    )
727);
728
729make_fn!(
730    trace_expression<SliceIter<Token>, Expression>,
731    do_each!(
732        pos => pos,
733        _ => word!("TRACE"),
734        expr => must!(wrap_err!(expression, "Expected failure message")),
735        (Expression::Debug(DebugDef{
736            pos: pos,
737            expr: Box::new(expr),
738        }))
739    )
740);
741
742make_fn!(
743    not_expression<SliceIter<Token>, Expression>,
744    do_each!(
745        pos => pos,
746        _ => word!("not"),
747        expr => must!(wrap_err!(expression, "Expected failure message")),
748        (Expression::Not(NotDef{
749            pos: pos,
750            expr: Box::new(expr),
751        }))
752    )
753);
754
755fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
756    let _input = input.clone();
757    either!(
758        input,
759        trace_parse!(format_expression),
760        trace_parse!(range_expression),
761        trace_parse!(simple_expression),
762        // cast parse attempts must happen before call parse attempts.
763        trace_parse!(cast_expression),
764        trace_parse!(call_expression),
765        trace_parse!(copy_expression)
766    )
767}
768
769make_fn!(
770    non_op_expression<SliceIter<Token>, Expression>,
771    either!(
772        trace_parse!(func_op_expression),
773        trace_parse!(func_expression),
774        trace_parse!(import_expression),
775        trace_parse!(trace_expression),
776        trace_parse!(not_expression),
777        trace_parse!(fail_expression),
778        trace_parse!(module_expression),
779        trace_parse!(alt_select_expression),
780        trace_parse!(grouped_expression),
781        trace_parse!(include_expression),
782        trace_parse!(unprefixed_expression)
783    )
784);
785
786pub fn expression(input: SliceIter<Token>) -> ParseResult<Expression> {
787    let _input = input.clone();
788    match trace_parse!(_input, op_expression) {
789        Result::Incomplete(i) => Result::Incomplete(i),
790        Result::Fail(_) => trace_parse!(input, non_op_expression),
791        Result::Abort(e) => Result::Abort(e),
792        Result::Complete(rest, expr) => Result::Complete(rest, expr),
793    }
794}
795
796make_fn!(
797    expression_statement<SliceIter<Token>, Statement>,
798    do_each!(
799        e => do_each!(
800            expr => trace_parse!(expression),
801            _ => must!(punct!(";")),
802            (expr)
803        ),
804        (Statement::Expression(e))
805    )
806);
807
808/// Verify binding is not a reserved word.
809macro_rules! match_binding_name {
810    ($i:expr,) => {{
811        use abortable_parser::{Error, Result};
812        let mut _i = $i.clone();
813        match match_type!(_i, BAREWORD) {
814            Result::Complete(i, t) => {
815                if t.fragment == "env" {
816                    return Result::Abort(Error::new(
817                        format!("Cannot use binding {}. It is a reserved word.", t.fragment),
818                        Box::new($i.clone()),
819                    ));
820                }
821                Result::Complete(i, t)
822            }
823            Result::Incomplete(i) => Result::Incomplete(i),
824            Result::Fail(e) => Result::Fail(e),
825            Result::Abort(e) => Result::Abort(e),
826        }
827    }};
828}
829
830make_fn!(
831    let_stmt_body<SliceIter<Token>, Statement>,
832    do_each!(
833        pos => pos,
834        name => wrap_err!(match_binding_name!(), "Expected name for binding"),
835        _ => optional!(trace_parse!(shape_suffix)),
836        _ => punct!("="),
837        val => trace_parse!(wrap_err!(expression, "Expected Expression to bind")),
838        _ => punct!(";"),
839        (Statement::Let(LetDef {
840            pos: pos,
841            name: name,
842            value: val,
843        }))
844    )
845);
846
847make_fn!(
848    let_statement<SliceIter<Token>, Statement>,
849    do_each!(
850        _ => word!("let"),
851        stmt => trace_parse!(must!(let_stmt_body)),
852        (stmt)
853    )
854);
855
856make_fn!(
857    assert_statement<SliceIter<Token>, Statement>,
858    do_each!(
859        pos => pos,
860        _ => word!("assert"),
861        expr => wrap_err!(must!(expression), "Expected Tuple {ok=<bool>, desc=<str>}"),
862        _ => must!(punct!(";")),
863        (Statement::Assert(pos, expr))
864    )
865);
866
867make_fn!(
868    out_statement<SliceIter<Token>, Statement>,
869    do_each!(
870        pos => pos,
871        _ => word!("out"),
872        typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"),
873        expr => wrap_err!(must!(expression), "Expected Expression to export"),
874        _ => must!(punct!(";")),
875        (Statement::Output(pos, typ.clone(), expr.clone()))
876    )
877);
878
879make_fn!(
880    print_statement<SliceIter<Token>, Statement>,
881    do_each!(
882        pos => pos,
883        _ => word!("convert"),
884        typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"),
885        expr => wrap_err!(must!(expression), "Expected Expression to print"),
886        _ => must!(punct!(";")),
887        (Statement::Print(pos, typ.clone(), expr.clone()))
888    )
889);
890
891//trace_macros!(true);
892fn statement(i: SliceIter<Token>) -> Result<SliceIter<Token>, Statement> {
893    return either!(
894        i,
895        trace_parse!(assert_statement),
896        trace_parse!(let_statement),
897        trace_parse!(out_statement),
898        trace_parse!(print_statement),
899        trace_parse!(expression_statement)
900    );
901}
902//trace_macros!(false);
903
904/// Parses a LocatedSpan into a list of Statements or an `error::Error`.
905pub fn parse<'a>(
906    input: OffsetStrIter<'a>,
907    comment_map: Option<&mut CommentMap>,
908) -> std::result::Result<Vec<Statement>, BuildError> {
909    match tokenize(input.clone(), comment_map) {
910        Ok(tokenized) => {
911            let mut out = Vec::new();
912            let mut i_ = SliceIter::new(&tokenized);
913            loop {
914                let i = i_.clone();
915                if let Some(tok) = i.peek_next() {
916                    if tok.typ == TokenType::END {
917                        break;
918                    }
919                }
920                match statement(i.clone()) {
921                    Result::Abort(e) => {
922                        return Err(BuildError::from(e));
923                    }
924                    Result::Fail(e) => {
925                        return Err(BuildError::from(e));
926                    }
927                    Result::Incomplete(_ei) => {
928                        let err = abortable_parser::Error::new(
929                            "Unexpected end of parse input",
930                            Box::new(i.clone()),
931                        );
932                        return Err(BuildError::from(err));
933                    }
934                    Result::Complete(rest, stmt) => {
935                        out.push(stmt);
936                        i_ = rest;
937                        if eoi(i).is_complete() {
938                            break;
939                        }
940                    }
941                }
942            }
943            return Ok(out);
944        }
945        Err(e) => {
946            return Err(e);
947        }
948    }
949}
950
951pub mod precedence;