Ast2

include lang

object ivy = {
    instantiate verb_base
    instantiate expr_base
    instantiate stmt_base(expr,":=",false)
    instantiate decl_base(expr,stmt)
Here, we parse statements specific to Ivy: var and assign.

    object stmt = { ...

        object varst = {
            variant this of stmt = struct {
                name : expr,
                ann : annot
            }

            action make (name:expr,ann:annot) returns (res:stmt) = {
                var s:this;
                s.name := name;
                s.ann := ann;
                res := s;
            }

            action encode(s:this,b:pretty,prio:verb) returns (b:pretty) = {
                b := s.ann.encode(b);
                if 0 < prio {
                    b := b.nest;
                    b := b.extend("{");
                    b := b.newline;
                };
                b := s.ann.encode(b);
                b := b.nest;
                b := b.extend("var");
                b := b.extend(" ");
                b := s.name.encode(b,0);
                b := b.extend(";");
                b := b.unnest;
                if 1 < prio {
                    b := b.unnest;
                    b := b.newline;
                    b := b.extend("}");
                };
            }
        }


        action parse_lang_stmt(st : pstate, prio:verb) returns(st : pstate, res:stmt) = {
            if st.tok = "var" {
                st := st.consume;
                var s : varst;
                (st,s.ann) := st.get_ann;
                (st,s.name) := expr.parse(st,0);
                if st.ok & st.tok = ";" {
                    st := st.consume;
                } else {
                    st.ok := st.tok = "}";  # allow to omit final semicolon
                };
                res := s;
            } else {
                var s : asgn;
                (st,s.ann) := st.get_ann;
                (st,s.lhs) := expr.parse(st,3);
                if st.ok & st.tok = ":=" {
                    st := st.consume;
                    (st,s.rhs) := expr.parse(st,0);
                    if st.ok & st.tok = ";" {
                        st := st.consume;
                    } else {
                        st.ok := st.tok = "}";  # allow to omit final semicolon
                    }
                }
                else {
                    st.ok := false;
                };
                res := s;
            }
        }
    }

    object groupdc = {
        variant this of decl = struct {
            decls : vector[decl]
        }

        action make(decls : vector[decl]) returns (res:decl) =
        {
            var s:this;
            s.decls := decls;
            res := s;
        }

        action encode(s:this,b:pretty,prio:verb) returns (b:pretty) = {
            b := b.nest;
            b := b.extend("{");
            var idx := s.decls.begin;
            while idx < s.decls.end {
                b := b.newline;
                b := s.decls.value(0).encode(b,0);
                idx := idx.next;
            };
            b := b.unnest;
            b := b.newline;
            b := b.extend("}");
        }
    }

    object decl = { ...
        action parse(st : pstate, prio:verb) returns(st : pstate, res:decl) = {
            if st.tok = "{" {
                st := st.consume;
                var s : groupdc;
                (st,s.decls) := parse_list(st,0);
                if st.tok = "}" {
                    st := st.consume;
                } else {st.ok := false};
                res := s
            }
            else if st.tok = "action" {
                st := st.consume;
                var s : actdc;
                (st,s.name) := expr.parse(st,0);
                if st.ok & st.tok = "(" {
                    (st,s.inputs) := expr.tup.parse(st,0);
                };
                if st.ok & st.tok = "returns" {
                    st := st.consume;
                    (st,s.outputs) := expr.tup.parse(st,0);
                };
                if st.ok & st.tok = "=" {
                    st := st.consume;
                    if st.tok = "{" {
                        (st,s.body) := stmt.parse(st,1);
                    } else {st.ok := false}
                } else {st.ok := false};
                res := s
            } else {st.ok := false}
        }
        action parse_list(st : pstate, prio:verb) returns(st : pstate, res:vector[decl]) = {
            while st.ok & st.tok.end > 0 & st.tok ~= "}" {
                var s : decl;
                (st,s) := parse(st,0);
                res := res.append(s);
            }
        }
    }
}

export ivy.expr.enc
export ivy.expr.dec
export ivy.expr.encdec
export ivy.stmt.enc
export ivy.stmt.dec
export ivy.stmt.encdec
export ivy.decl.enc
export ivy.decl.dec
export ivy.decl.encdec

import parse_error


export pretty.make
export pretty.extend
export pretty.flush

action pr(max:pos,s:str) returns (res:str) = {
    var p := pretty.make(max,4);
    var st := pstate.make(s);
    while st.tok.end > 0 {
    if st.tok = "(" {
        p := p.nest
    };
    p := p.extend(st.tok);
    if st.tok = ")" {
        p := p.unnest
    };
call show_pretty(p);
    if st.b.value(st.p) = 32 {
        p := p.extend(" ");
call show_pretty(p);
    };
    st := st.consume
    };

    p := p.flush;
    res := p.output
}

export pr
after init {

var p := pretty.make(11,4);
var st := pstate.make("fooooooo + (bar + baaaaaz)");
while st.tok.end > 0 {
if st.tok = "(" {
    p := p.nest
};
p := p.extend(st.tok);
if st.tok = ")" {
    p := p.unnest
};
call show_pretty(p);
if st.b.value(st.p) = 32 {
    p := p.extend(" ");
    call show_pretty(p);
};
st := st.consume
};

p := p.flush;
call show_pretty(p);

}

import action show_pretty(p:pretty)