# types Expr, Calcscanner defined in exprtrees.rs !use crate::exprtrees::*; /* ! lines are injected verbatim into parser */ !use crate::exprtrees::Expr::*; !use rustlr::{LBox}; lifetime 'src_lt absyntype Expr<'src_lt> externtype i64 nonterminals E ES terminals + - * / ( ) = ; terminals let in int var topsym ES resync ; left * 500 left / 500 left + 400 left - 400 left = 200 # for lexical scanner generation: lexvalue int Num(n) Val(n) lexvalue var Alphanum(x) Var(x) lexattribute set_line_comment("#") E --> int:m { m.value } E --> var:s { s.value } E --> E:e1 + E:e2 { Plus(e1.lbox(),parser.lbx(2,e2.value)) } E --> E:[e1] - E:[e2] { Minus(e1,e2)} E --> E:[e1] / E:[e2] { Divide(e1,e2) } E --> E:[e1] * E:[e2] { Times(e1,e2) } # give unary - higher precedence than binary -: E(600) --> - E:[e] { Negative(e) } E --> ( E:e ) { e.value } E --> let E:@Var(x)@ = E:[e] in E:[b] {Letexp(x,e,b)} ES --> E:[n] ; { Seq(vec![n]) } ES ==> ES:@Seq(mut v)@ E:[e] ; { v.push(e); Seq(v) } <== # ==> and <== are required for rules spanning multiple lines EOF alternatives: E --> var:@Var(v)@ { Var(v) } ES ==> ES:es@Seq(v)@ E:e ; { v.push(e.lbox()); es.value } <== --- Different kinds of patterns: E:a Simple label, a is the StackItem popped off stack, a.value is absyn value E:(a,b) Simple, irrefutable pattern, _item0_ is StackItem, (a,b) is .value E:@pat@: Pattern without label, _item0_ is StackItem, pat is bound to .value E:v@pat@: labeled pattern. _v_ is Stackitem, v is .value, pat is &mut v In this situation, v is moved out of _v_, which becomes useless.