/// <summary> /// Unify given expressions using tokens /// </summary> /// <param name="input1">first expression</param> /// <param name="input2">second expression</param> /// <param name="tokens">array of tokens to match</param> /// <returns>most general unifier</returns> public static IExpression Unify(string input1, string input2, params Token[] tokens) { var l1 = new Lexer(input1, tokens); var l2 = new Lexer(input2, tokens); return Unify(Eval(ref l1), Eval(ref l2)); }
/// <summary> /// Consumes Tokens from Lexer l until a expression is paresed completely /// </summary> /// <param name="l">Lexical analyzer if the expression to parse</param> /// <returns>parsed expression</returns> public static IExpression Eval(ref Lexer l) { if (!l.Next()) return null; IExpression expr; do { EvalToken(ref l, out expr); } while (expr == null && l.Next()); return expr; }
/// <summary> /// Consume next token /// </summary> /// <param name="l">the lexer</param> /// <param name="expr">output expression</param> static void EvalToken(ref Lexer l, out IExpression expr) { switch (l.Token) { case Token.QuotedString: case Token.Float: case Token.Int: case Token.False: case Token.True: if (FuncStack.Count == 0) { expr = new ValueExpression(l.Value); return; } ParamStack.Peek().Add(new ValueExpression(l.Value)); break; case Token.Variable: if (FuncStack.Count == 0) { expr = new VariableExpression(l.Value); return; } ParamStack.Peek().Add(new VariableExpression(l.Value)); break; case Token.Function: FuncStack.Push(l.Value); break; case Token.LeftBrace: ParamStack.Push(new List<IExpression>()); break; case Token.RightBrace: if(FuncStack.Count == 1) { var p = ParamStack.Pop().ToArray(); expr = new FunctionExpression(FuncStack.Pop(), p); return; } var param = ParamStack.Pop().ToArray(); ParamStack.Peek().Add(new FunctionExpression(FuncStack.Pop(),param)); break; case Token.Comma: case Token.Dot: case Token.Space: break; default: throw new ArgumentOutOfRangeException(); } expr = null; }