Skip to main content

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<'a>(s: &Token) -> ConvertResult<'a, Value> {
73    Ok(Value::Symbol(value_node!(
74        s.fragment.clone(),
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<'a>(s: &Token) -> ConvertResult<'a, Value> {
86    Ok(Value::Str(value_node!(s.fragment.clone(), s.pos.clone())))
87}
88
89// quoted_value is a quoted string.
90make_fn!(
91    quoted_value<SliceIter<Token>, Value>,
92    match_type!(STR => str_to_value)
93);
94
95// Helper function to make the return types work for down below.
96fn triple_to_number<'a>(
97    input: SliceIter<'a, Token>,
98    v: (Option<Token>, Option<Token>, Option<Token>),
99) -> ConvertResult<'a, Value> {
100    let (pref, mut pref_pos) = match v.0 {
101        None => ("", Position::new(0, 0, 0)),
102        Some(ref bs) => (bs.fragment.borrow(), bs.pos.clone()),
103    };
104
105    let has_dot = v.1.is_some();
106
107    if v.0.is_some() && !has_dot && v.2.is_none() {
108        let i = match FromStr::from_str(pref) {
109            Ok(i) => i,
110            Err(_) => {
111                return Err(Error::new(
112                    format!("Not an integer! {}", pref),
113                    Box::new(input.clone()),
114                ));
115            }
116        };
117        return Ok(Value::Int(value_node!(i, pref_pos)));
118    }
119
120    if v.0.is_none() && has_dot {
121        pref_pos = v.1.unwrap().pos;
122    }
123
124    let suf = match v.2 {
125        None => "".into(),
126        Some(bs) => bs.fragment,
127    };
128
129    let to_parse = pref.to_string() + "." + &suf;
130    let f = match FromStr::from_str(&to_parse) {
131        Ok(f) => f,
132        Err(_) => {
133            return Err(Error::new(
134                format!("Not a float! {}", to_parse),
135                Box::new(input.clone()),
136            ));
137        }
138    };
139    return Ok(Value::Float(value_node!(f, pref_pos)));
140}
141
142// trace_macros!(true);
143
144// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
145// alot. We need to process alternatives in order of decreasing
146// specificity.  Unfortunately this means we are required to go in a
147// decreasing size order which messes with either!'s completion logic. To
148// work around this we have to force Incomplete to be Error so that
149// either! will try the next in the series instead of aborting.
150//
151// *IMPORTANT*
152// It also means this combinator is risky when used with partial
153// inputs. So handle with care.
154fn number(input: SliceIter<Token>) -> Result<SliceIter<Token>, Value> {
155    let parsed = do_each!(input,
156         num => either!(
157             complete!(
158                  "Not a float",
159                  do_each!( // 1.0
160                      prefix => match_type!(DIGIT),
161                      has_dot => punct!("."),
162                      suffix => match_type!(DIGIT),
163                      (Some(prefix.clone()), Some(has_dot.clone()), Some(suffix.clone()))
164             )),
165             complete!(
166                  "Not a float",
167                  do_each!( // 1.
168                      prefix => match_type!(DIGIT),
169                      has_dot => punct!("."),
170                      (Some(prefix.clone()), Some(has_dot.clone()), None)
171             )),
172             complete!(
173                  "Not a float",
174                  do_each!( // .1
175                      has_dot => punct!("."),
176                      suffix => match_type!(DIGIT),
177                      (None, Some(has_dot.clone()), Some(suffix.clone()))
178             )),
179             do_each!( // 1
180                 prefix => match_type!(DIGIT),
181                 (Some(prefix.clone()), None, None)
182             )),
183         (num)
184    );
185    match parsed {
186        Result::Abort(e) => Result::Abort(e),
187        Result::Fail(e) => Result::Fail(e),
188        Result::Incomplete(offset) => Result::Incomplete(offset),
189        Result::Complete(rest, triple) => {
190            let num = triple_to_number(rest.clone(), triple);
191            match num {
192                Ok(val) => Result::Complete(rest, val),
193                Err(e) => Result::Fail(e),
194            }
195        }
196    }
197}
198// trace_macros!(false);
199
200make_fn!(
201    boolean_value<SliceIter<Token>, Value>,
202    do_each!(
203        b => match_type!(BOOLEAN),
204        (Value::Boolean(PositionedItem{
205            val: b.fragment.as_ref() == "true",
206            pos: b.pos,
207        }))
208    )
209);
210
211make_fn!(
212    field_value<SliceIter<Token>, (Token, Option<Expression>, Expression)>,
213    do_each!(
214            field => wrap_err!(either!(match_type!(BOOLEAN), match_type!(BAREWORD), match_type!(STR)),
215                               "Field names must be a bareword or a string."),
216            constraint => optional!(shape_suffix),
217            _ => must!(punct!("=")),
218            value => must!(expression),
219            (field, constraint, value)
220    )
221);
222
223// Helper function to make the return types work for down below.
224fn vec_to_tuple(pos: Position, fields: Option<FieldList>) -> Value {
225    Value::Tuple(value_node!(fields.unwrap_or(Vec::new()), pos))
226}
227
228make_fn!(
229    field_list<SliceIter<Token>, FieldList>,
230    separated!(punct!(","), field_value)
231);
232
233make_fn!(
234    tuple<SliceIter<Token>, Value>,
235    do_each!(
236        pos => pos,
237        _ => punct!("{"),
238        v => optional!(field_list),
239        _ => optional!(punct!(",")),
240        _ => must!(punct!("}")),
241        (vec_to_tuple(pos, v))
242    )
243);
244
245fn tuple_to_list<Sp: Into<Position>>(pos: Sp, elems: Option<Vec<Expression>>) -> Value {
246    Value::List(ListDef {
247        elems: elems.unwrap_or_else(|| Vec::new()),
248        pos: pos.into(),
249    })
250}
251
252make_fn!(
253    list_value<SliceIter<Token>, Value>,
254    do_each!(
255        start => punct!("["),
256        elements => optional!(separated!(punct!(","), expression)),
257        _ => optional!(punct!(",")),
258        _ => must!(punct!("]")),
259        (tuple_to_list(start.pos, elements))
260    )
261);
262
263make_fn!(
264    empty_value<SliceIter<Token>, Value>,
265    do_each!(
266        pos => pos,
267        _ => match_type!(EMPTY),
268        (Value::Empty(pos.into()))
269    )
270);
271
272make_fn!(
273    compound_value<SliceIter<Token>, Value>,
274    either!(trace_parse!(list_value), trace_parse!(tuple))
275);
276
277make_fn!(
278    value<SliceIter<Token>, Value>,
279    either!(
280        trace_parse!(symbol),
281        trace_parse!(compound_value),
282        trace_parse!(boolean_value),
283        trace_parse!(empty_value),
284        trace_parse!(number),
285        trace_parse!(quoted_value)
286    )
287);
288
289make_fn!(
290    shape_suffix<SliceIter<Token>, Expression>,
291    do_each!(
292        _ => punct!("::"),
293        shape => non_op_expression,
294        (shape)
295    )
296);
297
298fn value_to_expression(v: Value) -> Expression {
299    Expression::Simple(v)
300}
301
302make_fn!(
303    simple_expression<SliceIter<Token>, Expression>,
304    do_each!(
305        val => trace_parse!(value),
306        _ => not!(either!(punct!("{"), punct!("["), punct!("("))),
307        (value_to_expression(val))
308    )
309);
310
311fn expression_to_grouped_expression(e: Expression, pos: Position) -> Expression {
312    Expression::Grouped(Box::new(e), pos)
313}
314
315make_fn!(
316    grouped_expression<SliceIter<Token>, Expression>,
317    do_each!(
318        pos => pos,
319        _ => punct!("("),
320        expr => do_each!(
321            expr => trace_parse!(expression),
322            _ => must!(punct!(")")),
323            (expr)
324        ),
325        (expression_to_grouped_expression(expr, pos))
326    )
327);
328
329fn tuple_to_copy(sym: Value, fields: Option<FieldList>) -> Expression {
330    let pos = sym.pos().clone();
331    let fields = match fields {
332        Some(fields) => fields,
333        None => Vec::new(),
334    };
335    Expression::Copy(CopyDef {
336        selector: sym,
337        fields: fields,
338        pos: pos,
339    })
340}
341
342make_fn!(
343    copy_expression<SliceIter<Token>, Expression>,
344    do_each!(
345        sym => trace_parse!(symbol),
346        _ => punct!("{"),
347        fields => optional!(trace_parse!(field_list)),
348        _ => optional!(punct!(",")),
349        _ => must!(punct!("}")),
350        (tuple_to_copy(sym, fields))
351    )
352);
353
354fn tuple_to_func<'a>(
355    pos: Position,
356    vals: Option<Vec<(Value, Option<Expression>)>>,
357    val: Expression,
358) -> ConvertResult<'a, Expression> {
359    let mut default_args = match vals {
360        None => Vec::new(),
361        Some(vals) => vals,
362    };
363    let arglist = default_args
364        .drain(0..)
365        .map(|(s, constraint)| {
366            (
367                PositionedItem {
368                    pos: s.pos().clone(),
369                    val: s.to_string().into(),
370                },
371                constraint,
372            )
373        })
374        .collect();
375    Ok(Expression::Func(FuncDef {
376        scope: None,
377        argdefs: arglist,
378        fields: Box::new(val),
379        pos: pos,
380    }))
381}
382
383make_fn!(
384    arglist<SliceIter<Token>, Vec<(Value, Option<Expression>)>>,
385    separated!(
386        punct!(","),
387        do_each!(
388            sym => symbol,
389            constraint => optional!(shape_suffix),
390            (sym, constraint)
391        )
392    )
393);
394
395fn module_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
396    let parsed = do_each!(input,
397        pos => pos,
398        _ => word!("module"),
399        _ => must!(punct!("{")),
400        arglist => trace_parse!(optional!(field_list)),
401        _ => optional!(punct!(",")),
402        _ => must!(punct!("}")),
403        _ => must!(punct!("=>")),
404        out_expr_and_constraint => optional!(
405            do_each!(
406                _ => punct!("("),
407                expr => must!(expression),
408                constraint => optional!(shape_suffix),
409                _ => must!(punct!(")")),
410                (expr, constraint)
411            )
412        ),
413        _ => must!(punct!("{")),
414        stmt_list =>  trace_parse!(repeat!(statement)),
415        _ => must!(punct!("}")),
416        (pos, arglist, out_expr_and_constraint, stmt_list)
417    );
418    match parsed {
419        Result::Abort(e) => Result::Abort(e),
420        Result::Fail(e) => Result::Fail(e),
421        Result::Incomplete(offset) => Result::Incomplete(offset),
422        Result::Complete(rest, (pos, arglist, out_expr_and_constraint, stmt_list)) => {
423            let mut def = ModuleDef::new(arglist.unwrap_or_else(|| Vec::new()), stmt_list, pos);
424            if let Some((expr, constraint)) = out_expr_and_constraint {
425                def.set_out_expr(expr);
426                def.out_constraint = constraint.map(Box::new);
427            }
428            Result::Complete(rest, Expression::Module(def))
429        }
430    }
431}
432
433fn func_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
434    let parsed = do_each!(input,
435        pos => pos,
436        _ => word!("func"),
437        _ => must!(punct!("(")),
438        arglist => trace_parse!(optional!(arglist)),
439        _ => must!(punct!(")")),
440        _ => must!(punct!("=>")),
441        map =>  trace_parse!(expression),
442        (pos, arglist, map)
443    );
444    match parsed {
445        Result::Abort(e) => Result::Abort(e),
446        Result::Fail(e) => Result::Fail(e),
447        Result::Incomplete(offset) => Result::Incomplete(offset),
448        Result::Complete(rest, (pos, arglist, map)) => match tuple_to_func(pos, arglist, map) {
449            Ok(expr) => Result::Complete(rest, expr),
450            Err(e) => Result::Fail(Error::caused_by(
451                "Invalid func syntax",
452                Box::new(e),
453                Box::new(rest.clone()),
454            )),
455        },
456    }
457}
458
459make_fn!(
460    alt_select_expression<SliceIter<Token>, Expression>,
461    do_each!(
462        pos => pos,
463        _ => word!("select"),
464        _ => must!(punct!("(")),
465        val => must!(expression),
466        default => optional!(
467            do_each!(
468                _ => punct!(","),
469                def => must!(expression),
470                (def)
471            )
472        ),
473        _ => optional!(punct!(",")),
474        _ => must!(punct!(")")),
475        _ => must!(punct!("=>")),
476        _ => must!(punct!("{")),
477        tpl => must!(field_list),
478        _ => optional!(punct!(",")),
479        _ => must!(punct!("}")),
480        (Expression::Select(SelectDef {
481            val: Box::new(val),
482            default: default.map(|e| Box::new(e)),
483            tuple: tpl,
484            pos: pos,
485        }))
486    )
487);
488
489make_fn!(
490    simple_format_args<SliceIter<Token>, FormatArgs>,
491    do_each!(
492        _ => punct!("("),
493        args => separated!(punct!(","), trace_parse!(expression)),
494        _ => must!(punct!(")")),
495        (FormatArgs::List(args))
496    )
497);
498
499make_fn!(
500    expression_format_args<SliceIter<Token>, FormatArgs>,
501    do_each!(
502        expr => must!(expression),
503        (FormatArgs::Single(Box::new(expr)))
504    )
505);
506
507make_fn!(
508    format_expression<SliceIter<Token>, Expression>,
509    do_each!(
510        tmpl => match_type!(STR),
511        _ => punct!("%"),
512        args => wrap_err!(must!(either!(simple_format_args, expression_format_args)),
513            "Expected format arguments"),
514        (Expression::Format(FormatDef {
515            template: tmpl.fragment.to_string(),
516            args: args,
517            pos: tmpl.pos,
518        }))
519    )
520);
521
522make_fn!(
523    include_expression<SliceIter<Token>, Expression>,
524    do_each!(
525        pos => pos,
526        _ => word!("include"),
527        typ => must!(match_type!(BAREWORD)),
528        path => must!(match_type!(STR)),
529        (Expression::Include(IncludeDef{
530            pos: pos,
531            typ: typ,
532            path: path,
533        }))
534    )
535);
536
537fn tuple_to_call<'a>(
538    input: SliceIter<'a, Token>,
539    val: Value,
540    exprs: Option<Vec<Expression>>,
541) -> ConvertResult<'a, Expression> {
542    if let Value::Symbol(_) = val {
543        Ok(Expression::Call(CallDef {
544            funcref: val,
545            arglist: exprs.unwrap_or_else(|| Vec::new()),
546            pos: (&input).into(),
547        }))
548    } else {
549        Err(Error::new(
550            format!("Expected Selector Got {:?}", val),
551            Box::new(input.clone()),
552        ))
553    }
554}
555
556make_fn!(
557    cast_expression<SliceIter<Token>, Expression>,
558    do_each!(
559        typ => either!(
560            word!("int"),
561            word!("float"),
562            word!("str"),
563            word!("bool")
564        ),
565        _ => punct!("("),
566        expr => expression,
567        _ => punct!(")"),
568        (Expression::Cast(CastDef{
569            cast_type: match typ.fragment.as_ref() {
570                "int" => CastType::Int,
571                "float" => CastType::Float,
572                "str" => CastType::Str,
573                "bool" => CastType::Bool,
574                _ => unreachable!(),
575            },
576            target: Box::new(expr),
577            pos: typ.pos,
578        }))
579    )
580);
581
582fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
583    let parsed = do_each!(input.clone(),
584        callee_name => trace_parse!(symbol),
585        _ => punct!("("),
586        args => optional!(separated!(punct!(","), trace_parse!(expression))),
587        _ => optional!(punct!(",")),
588        _ => must!(punct!(")")),
589        (callee_name, args)
590    );
591    match parsed {
592        Result::Abort(e) => Result::Abort(e),
593        Result::Fail(e) => Result::Fail(e),
594        Result::Incomplete(offset) => Result::Incomplete(offset),
595        Result::Complete(rest, (name, args)) => match tuple_to_call(input.clone(), name, args) {
596            Ok(expr) => Result::Complete(rest, expr),
597            Err(e) => Result::Fail(Error::caused_by(
598                "Invalid Call Syntax",
599                Box::new(e),
600                Box::new(rest),
601            )),
602        },
603    }
604}
605
606make_fn!(
607    reduce_expression<SliceIter<Token>, Expression>,
608    do_each!(
609        pos => pos,
610        _ => word!("reduce"),
611        _ => must!(punct!("(")),
612        func => must!(expression),
613        _ => must!(punct!(",")),
614        acc => must!(trace_parse!(expression)),
615        _ => must!(punct!(",")),
616        tgt => must!(trace_parse!(expression)),
617        _ => optional!(punct!(",")),
618        _ => must!(punct!(")")),
619        (Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{
620            func: Box::new(func),
621            acc: Box::new(acc),
622            target: Box::new(tgt),
623            pos: pos,
624        })))
625    )
626);
627
628make_fn!(
629    map_expression<SliceIter<Token>, Expression>,
630    do_each!(
631        pos => pos,
632        _ => word!("map"),
633        _ => must!(punct!("(")),
634        func => must!(expression),
635        _ => must!(punct!(",")),
636        list => must!(trace_parse!(expression)),
637        _ => optional!(punct!(",")),
638        _ => must!(punct!(")")),
639        (Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{
640            func: Box::new(func),
641            target: Box::new(list),
642            pos: pos,
643        })))
644    )
645);
646
647make_fn!(
648    filter_expression<SliceIter<Token>, Expression>,
649    do_each!(
650        pos => pos,
651        _ => word!("filter"),
652        _ => must!(punct!("(")),
653        func => must!(expression),
654        _ => must!(punct!(",")),
655        list => must!(trace_parse!(expression)),
656        _ => optional!(punct!(",")),
657        _ => must!(punct!(")")),
658        (Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{
659            func: Box::new(func),
660            target: Box::new(list),
661            pos: pos,
662        })))
663    )
664);
665
666make_fn!(
667    func_op_expression<SliceIter<Token>, Expression>,
668    either!(reduce_expression, map_expression, filter_expression)
669);
670
671make_fn!(
672    range_expression<SliceIter<Token>, Expression>,
673    do_each!(
674        pos => pos,
675        start => either!(simple_expression, grouped_expression),
676        _ => punct!(":"),
677        maybe_step => optional!(
678            do_each!(
679                step => either!(simple_expression, grouped_expression),
680                _ => punct!(":"),
681                (Box::new(step))
682            )
683        ),
684        end => must!(wrap_err!(either!(simple_expression, grouped_expression), "Expected simple or grouped expression")),
685        (Expression::Range(RangeDef{
686            pos: pos,
687            start: Box::new(start),
688            step: maybe_step,
689            end: Box::new(end),
690        }))
691    )
692);
693
694make_fn!(
695    import_expression<SliceIter<Token>, Expression>,
696    do_each!(
697        pos => pos,
698        _ => word!("import"),
699        path => must!(wrap_err!(match_type!(STR), "Expected import path")),
700        (Expression::Import(ImportDef{
701            pos: pos,
702            path: path,
703        }))
704    )
705);
706
707make_fn!(
708    string_expression<SliceIter<Token>, Expression>,
709    do_each!(
710        val => trace_parse!(quoted_value),
711        (value_to_expression(val))
712    )
713);
714
715make_fn!(
716    fail_expression<SliceIter<Token>, Expression>,
717    do_each!(
718        pos => pos,
719        _ => word!("fail"),
720        msg => must!(wrap_err!(expression, "Expected failure message")),
721        (Expression::Fail(FailDef{
722            pos: pos,
723            message: Box::new(msg),
724        }))
725    )
726);
727
728make_fn!(
729    trace_expression<SliceIter<Token>, Expression>,
730    do_each!(
731        pos => pos,
732        _ => word!("TRACE"),
733        expr => must!(wrap_err!(expression, "Expected failure message")),
734        (Expression::Debug(DebugDef{
735            pos: pos,
736            expr: Box::new(expr),
737        }))
738    )
739);
740
741make_fn!(
742    not_expression<SliceIter<Token>, Expression>,
743    do_each!(
744        pos => pos,
745        _ => word!("not"),
746        expr => must!(wrap_err!(expression, "Expected failure message")),
747        (Expression::Not(NotDef{
748            pos: pos,
749            expr: Box::new(expr),
750        }))
751    )
752);
753
754fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
755    let _input = input.clone();
756    either!(
757        input,
758        trace_parse!(format_expression),
759        trace_parse!(range_expression),
760        trace_parse!(simple_expression),
761        // cast parse attempts must happen before call parse attempts.
762        trace_parse!(cast_expression),
763        trace_parse!(call_expression),
764        trace_parse!(copy_expression)
765    )
766}
767
768make_fn!(
769    non_op_expression<SliceIter<Token>, Expression>,
770    either!(
771        trace_parse!(func_op_expression),
772        trace_parse!(func_expression),
773        trace_parse!(import_expression),
774        trace_parse!(trace_expression),
775        trace_parse!(not_expression),
776        trace_parse!(fail_expression),
777        trace_parse!(module_expression),
778        trace_parse!(alt_select_expression),
779        trace_parse!(grouped_expression),
780        trace_parse!(include_expression),
781        trace_parse!(unprefixed_expression)
782    )
783);
784
785pub fn expression(input: SliceIter<Token>) -> ParseResult<Expression> {
786    let _input = input.clone();
787    match trace_parse!(_input, op_expression) {
788        Result::Incomplete(i) => Result::Incomplete(i),
789        Result::Fail(_) => trace_parse!(input, non_op_expression),
790        Result::Abort(e) => Result::Abort(e),
791        Result::Complete(rest, expr) => Result::Complete(rest, expr),
792    }
793}
794
795make_fn!(
796    expression_statement<SliceIter<Token>, Statement>,
797    do_each!(
798        e => do_each!(
799            expr => trace_parse!(expression),
800            _ => must!(punct!(";")),
801            (expr)
802        ),
803        (Statement::Expression(e))
804    )
805);
806
807/// Verify binding is not a reserved word.
808macro_rules! match_binding_name {
809    ($i:expr,) => {{
810        use abortable_parser::{Error, Result};
811        let mut _i = $i.clone();
812        match match_type!(_i, BAREWORD) {
813            Result::Complete(i, t) => {
814                if t.fragment.as_ref() == "env" {
815                    return Result::Abort(Error::new(
816                        format!("Cannot use binding {}. It is a reserved word.", t.fragment),
817                        Box::new($i.clone()),
818                    ));
819                }
820                Result::Complete(i, t)
821            }
822            Result::Incomplete(i) => Result::Incomplete(i),
823            Result::Fail(e) => Result::Fail(e),
824            Result::Abort(e) => Result::Abort(e),
825        }
826    }};
827}
828
829make_fn!(
830    let_stmt_body<SliceIter<Token>, Statement>,
831    do_each!(
832        pos => pos,
833        name => wrap_err!(match_binding_name!(), "Expected name for binding"),
834        constraint => optional!(trace_parse!(shape_suffix)),
835        _ => punct!("="),
836        val => trace_parse!(wrap_err!(expression, "Expected Expression to bind")),
837        _ => punct!(";"),
838        (Statement::Let(LetDef {
839            pos: pos,
840            name: name,
841            constraint: constraint,
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;