// 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); }
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); }