public static void LambdaCalculus(string program, string parsed, string eval) { var term = LcTerm.Parse(program); var env = System.Collections.Immutable.ImmutableDictionary.Create <string, LcTerm>(); Assert.Equal(parsed, term.ToString()); Assert.Equal(eval, term.Eval(env)?.ToString()); }
static bool Parse(Input inp, ref Position pos, ref Rules rules, out LcTerm x) { inp.WhiteSpaces(ref pos); return(LcApply(inp, ref pos, ref rules, out x) || LcLambda(inp, ref pos, ref rules, out x) || LcBracketed(inp, ref pos, ref rules, out x) || LcVar(inp, ref pos, out x)); }
static bool LcVar(Input inp, ref Position pos, out LcTerm x) { if (inp.Letters(ref pos, out var name)) { x = new LcVar { Name = name.ToString(), Position = pos.Pos }; return(true); } x = default; return(false); }
static bool LcBracketed(Input inp, ref Position pos, ref Rules rules, out LcTerm x) { var i = pos; if (inp.Char('(', ref i) && Parse(inp, ref i, ref rules, out x) && inp.Optional(inp.WhiteSpaces(ref i)) && inp.Char(')', ref i)) { return(pos.Seek(i, ref rules)); } return(Recognizers.Fail(out x)); }
static bool LcApply(Input inp, ref Position pos, ref Rules rules, out LcTerm x) { var i = pos; if (!rules.IsLoop(1) && Parse(inp, ref i, ref rules, out var lambda) && inp.WhiteSpaces(ref i) && Parse(inp, ref i, ref rules, out var arg)) { x = new LcApply { Lambda = lambda, Arg = arg }; return(pos.Seek(i, ref rules)); } return(Recognizers.Fail(out x)); }
static bool LcLambda(Input inp, ref Position pos, ref Rules rules, out LcTerm x) { var i = pos; if (inp.Letters(ref i, out var v) && inp.Optional(inp.WhiteSpaces(ref i)) && inp.Literal("->", ref i) && Parse(inp, ref i, ref rules, out var body)) { x = new LcLambda { Var = v.ToString(), Body = body }; return(pos.Seek(i, ref rules)); } return(Recognizers.Fail(out x)); }