Example #1
0
        private SExp.SExp EatExpression(IToken startExpToken)
        {
            var exp   = new SExp.SExp(startExpToken.Line, startExpToken.Column, new List <SExpNode>());
            var token = _lexer.Eat();

            do
            {
                switch (token.Kind)
                {
                case TokenKind.StartExpression:
                    exp.Nodes.Add(EatExpression(token));
                    break;

                case TokenKind.EndExpression:
                    if (exp.Nodes.Count > 0 && exp.Nodes[0] is Atom atom && atom.Token is IdentifierToken idToken &&
                        _systemFunctionTable.TryGet(idToken.Value, out var function))
                    {
                        exp.Nodes.RemoveAt(0);
                        exp = new FunctionSExp(function, token.Line, token.Column, exp.Nodes);
                    }
                    else if (exp.Nodes.Count > 0)
                    {
                        exp = new FunctionSExp(_systemFunctionTable.Get("list"), token.Line, token.Column,
                                               exp.Nodes);
                    }

                    return(exp);

                case TokenKind.DoubleLiteral:
                case TokenKind.IntegerLiteral:
                case TokenKind.StringLiteral:
                case TokenKind.Identifier:
                    exp.Nodes.Add(new Atom(token.Line, token.Column, token));
                    break;
Example #2
0
        private object ExecuteFunction(FunctionSExp fexp)
        {
            var args = new Func <object> [fexp.Nodes.Count];

            if (fexp.Nodes.Count > 0)
            {
                for (var i = 0; i < fexp.Nodes.Count; i++)
                {
                    var node = fexp.Nodes[i];

                    Func <object> nodeValueFunc;
                    switch (node)
                    {
                    case FunctionSExp childFExp:
                        nodeValueFunc = () => ExecuteFunction(childFExp);
                        break;

                    case Atom childAtom:
                        if (!(fexp.Function is DefFunction) && !(fexp.Function is DefFuncFunction) &&
                            !(fexp.Function is ParamsFunction) &&
                            childAtom.Token is IdentifierToken idToken)
                        {
                            nodeValueFunc = () =>
                            {
                                if (_scopeManager.Contains(idToken.Value))
                                {
                                    return(_scopeManager.Get(idToken.Value));
                                }

                                if (_customFunctionTable.Contains(idToken.Value))
                                {
                                    return(_customFunctionTable.GetCustomFunction(idToken.Value));
                                }

                                if (_systemFunctionTable.TryGet(idToken.Value, out var sysFunc))
                                {
                                    return(sysFunc);
                                }

                                throw new InvalidOperationException($"Unknown identifier '{idToken}'");
                            };
                        }
                        else
                        {
                            nodeValueFunc = () => childAtom.Token.Value;
                        }

                        break;

                    // this will be an empty parameter list
                    case SExp.SExp _:
                        nodeValueFunc = () => new object[0];
                        break;

                    default:
                        throw new InvalidOperationException($"Expected a function or atom but encountered: {node}");
                    }

                    args[i] = nodeValueFunc;
                }
            }

            CheckCallingArgs(fexp.Function, args);

            return(fexp.Function.Execute(args));
        }