lambdascript 0.1.0

Educational tool illustrating beta reduction of untyped lambda terms, parser generation
# Grammar for lambda calculus with step-by-step reduction

!use rustlr::{LBox,unbox};
!use crate::untyped::*;
!use crate::untyped::Term::*;

absyntype Term
externtype Vec<LBox<Term>>
terminals lambda lam Lam ( ) [ ] DOT let = in define lazy weak CBV Liang ;
terminal INTEGER
terminal ID
nonterminals T F Fs
nonterminal Vars
#nonterminal Moreargs
nonterminal LAMSYM
nonterminal Ts
topsym Ts
resync ;

# place defs in exstate
Ts --> T:x ;  { parser.exstate.push(x.lbox()); Nothing }
Ts --> Ts T:x ;  { parser.exstate.push(x.lbox()); Nothing }

# precedence order: T > Fs > F, Fs defines left-associative application.
# application binds tighter than abstraction.
Fs --> F:@a@ { a }
Fs --> Fs:a F:b { App(a.lbox(), b.lbox()) }

F --> ID:(x) { x } /* var */
F --> INTEGER:(x) { x } /* const*/

T --> Fs:@a@ { a }
F --> ( T:@a@ ) { a }

T --> CBV F:x { CBV(x.lbox()) }
T --> weak F:x { Weak(x.lbox()) }

#T --> LAMSYM ID:@Var(x)@ DOT T:b { Abs(x,b.lbox()) }
T ==> LAMSYM Vars:@Seq(mut vs)@ DOT T:b  {
  let mut t = b.value;
  while vs.len()>0 {
    t = Abs(getvar(&unbox!(vs.pop().unwrap())),parser.lbx(0,t));
  }
  return t; }
  <==

Vars --> ID:x { Seq(vec![x.lbox()]) }
Vars --> Vars:@Seq(mut vs)@ ID:y { vs.push(y.lbox()); Seq(vs) }


T --> let ID:@Var(x)@ = T:v in T:b  { App(parser.lbx(0,Abs(x,b.lbox())), v.lbox()) }


# define evaluate to the term being defined, but also affects global env
T ==> define ID:@Var(x)@ = T:v {
  let nv = Def(true,x,v.lbox());
  //parser.exstate.push(parser.lbx(0,nv));
  nv 
 } <==

T ==> define lazy ID:@Var(x)@ = T:v {
  let nv = Def(false,x,v.lbox());
  nv 
 } <==

LAMSYM --> lambda | lam | Lam

EOF


Everything after EOF is ignored ... alternate productions below are not
part of the grammar.

F ==> F:a Moreargs:@Seq(mut ts)@  {
  if ts.len()<1 {return a.value;}
  let mut apterm = App(a.lbox(), ts.pop().unwrap());
  while ts.len()>0 {
    apterm = App(parser.lbx(0,apterm), ts.pop().unwrap());
  }
  apterm }
  <==

T ==> LAMSYM Vars:@Seq(mut vs)@ DOT T:b  {
  let mut t = b.value;
  while vs.len()>0 {
    t = Abs(getvar(&unbox!(vs.pop().unwrap())),parser.lbx(0,t));
  }
  return t; }
  <==

Moreargs --> F:b { Seq(vec![b.lbox()]) }
Moreargs --> F:b Moreargs:ms@Seq(ts)@ { ts.push(b.lbox()); ms.value }

Vars --> ID:x { Seq(vec![x.lbox()]) }
Vars --> Vars:@Seq(mut vs)@ ID:y { vs.push(y.lbox()); Seq(vs) }