Beispiel #1
0
        // Pre-parse on the current level for functions, indexing, sequences
        // Convert from raw style-form to interprettable expression tree
        public static ExprC parse(SExpression rawExpr)
        {
            SExpression expr = preParse(rawExpr);

            ExprC result;

            // Check arg counts and expr object classes for errors
            // Convert to appropriate expression tree (w/ correct subtree)
            switch (expr.type)
            {
            case SExpression.FormatType.Document:
                if (expr.children.Count < 1)
                {
                    throw new ParseException("Incorrect Child Number: Document");
                }
                foreach (SExpression child in expr.children)
                {
                    if (child.type != SExpression.FormatType.Statement)
                    {
                        throw new ParseException("Document with non-Statement children");
                    }
                }
                result = new SeqC(parseEach(expr.children));
                break;

            case SExpression.FormatType.Statement:
                if (expr.children.Count > 1)
                {
                    throw new ParseException("Incorrect Child Number: Statement");
                }
                else if (expr.children.Count == 0)
                {
                    throw new ParseException("Empty statement");
                }
                result = parse(expr.children[0]);
                break;

            case SExpression.FormatType.Bold:
                if (expr.children.Count != 3)
                {
                    throw new ParseException("Incorrect Child Number: Conditional");
                }
                result = new IfC(parse(expr.children[0]),
                                 parse(expr.children[1]),
                                 parse(expr.children[2]));
                break;

            case SExpression.FormatType.Italic:
                if (expr.children.Count < 2)
                {
                    throw new ParseException("Incorrect Child Number: Addition");
                }
                result = new AddC(parseEach(expr.children));
                break;

            case SExpression.FormatType.Under:
                if (expr.children.Count != 2)
                {
                    throw new ParseException("Incorrect Child Number: Binding");
                }
                result = new BindC(parse(expr.children[0]), parse(expr.children[1]));
                break;

            case SExpression.FormatType.Strike:
                if (expr.children.Count != 1)
                {
                    throw new ParseException("Incorrect Child Number: Negation");
                }
                result = new NegC(parse(expr.children[0]));
                break;

            case SExpression.FormatType.Size:
                if (expr.children.Count != 1)
                {
                    throw new ParseException("Incorrect Child Number: Grouping");
                }
                result = parse(expr.children[0]);
                break;

            case SExpression.FormatType.Color:
                if (expr.children.Count != 1)
                {
                    throw new ParseException("Incorrect Child Number: Integer Literal");
                }
                result = new NumC(expr.value);
                break;

            case SExpression.FormatType.String:
                if (expr.children.Count != 0)
                {
                    throw new ParseException("Incorrect Child Number: Identifier");
                }
                if (!(expr is SString))
                {
                    throw new ParseException("String type on non-SString");
                }
                result = new IdC(((SString)expr).str);
                break;

            case SExpression.FormatType.Function:
                if (expr.children.Count < 1)
                {
                    throw new ParseException("Incorrect Child Number: Function");
                }
                if (!(expr is SWithArgs))
                {
                    throw new ParseException("Function type on non-SWithArgs");
                }
                result = new FuncC(parse(((SWithArgs)expr).baseExp), parseEach(expr.children));
                break;

            case SExpression.FormatType.Index:
                if (expr.children.Count < 1)
                {
                    throw new ParseException("Incorrect Child Number: Index");
                }
                if (!(expr is SWithArgs))
                {
                    throw new ParseException("Index type on non-SWithArgs");
                }
                result = new IndexC(parse(((SWithArgs)expr).baseExp), parseEach(expr.children));
                break;

            case SExpression.FormatType.Sequence:
                if (expr.children.Count < 1)
                {
                    throw new ParseException("Incorrect Child Number: Sequence");
                }
                result = new SeqC(parseEach(expr.children));
                break;

            case SExpression.FormatType.Font:
                if (expr.children.Count != 1)
                {
                    throw new ParseException("Incorrect Child Number: String Literal");
                }
                if (!(expr.children[0] is SString))
                {
                    throw new ParseException("String Literal with non-string identifier");
                }
                result = new StrC(((SString)expr.children[0]).str);
                break;

            default:
            case SExpression.FormatType.Sub:
            case SExpression.FormatType.Super:
                throw new ParseException("Impossible SExpression type");
            }

            return(result);
        }
Beispiel #2
0
        public override Val interp(Environment env)
        {
            Val result;

            if (lexpr is IdC) // binding a variable
            {
                result = rexpr.interp(env);
                env[((IdC)lexpr).sym] = result;
            }
            else if (lexpr is FuncC) // defining a function
            {
                FuncC lexprFunc = (FuncC)lexpr;

                if (lexprFunc.func is IdC)
                {
                    List <string> parms = new List <string>();
                    foreach (ExprC parm in lexprFunc.args)
                    {
                        if (parm is IdC)
                        {
                            parms.Add(((IdC)parm).sym);
                        }
                        else
                        {
                            throw new InterpException("Malformed function definition params");
                        }
                    }
                    result = new CloV((Environment)env.Clone(), rexpr, parms);
                    ((CloV)result).env.SetLocal(((IdC)lexprFunc.func).sym, result); // allow recursion
                    env[((IdC)lexprFunc.func).sym] = result;
                }
                else
                {
                    throw new InterpException("Malformed function definition name");
                }
            }
            else if (lexpr is IndexC) // defining an array or setting an element
            {
                IndexC lexprArray = (IndexC)lexpr;

                if (lexprArray.arr is IdC)
                {
                    List <long> indices = new List <long>();
                    foreach (ExprC idx in lexprArray.indices)
                    {
                        Val idxVal = idx.interp(env);

                        if (idxVal is NumV)
                        {
                            indices.Add(((NumV)idxVal).num);
                        }
                        else
                        {
                            throw new InterpException("Non-numeric array index");
                        }
                    }

                    if (env.ContainsKey(((IdC)lexprArray.arr).sym)) // setting element
                    {
                        ArrV arr = lexprArray.arr.interp(env) as ArrV;
                        if (arr == null)
                        {
                            throw new InterpException("Indexing non-array");
                        }
                        result = rexpr.interp(env);
                        arr.SetValue(indices, result);
                    }
                    else // defining new array
                    {
                        result = new ArrV(indices, rexpr.interp(env));
                        env[((IdC)lexprArray.arr).sym] = result;
                    }
                }
                else
                {
                    throw new InterpException("Malformed array definition name");
                }
            }
            else
            {
                throw new InterpException("Binding with invalid lvalue");
            }

            return(result);
        }