Expr SubscriptExprs(Expr[] indexExprs, Expr[] dimExprs) { if (indexExprs == null) return null; if (indexExprs.Length == 1) return indexExprs[0]; // special case: single index is always OK if (indexExprs.Length < dimExprs.Length) { throw new ParseException("Not enough subscripts", indexExprs[indexExprs.Length - 1].Token); } else if (indexExprs.Length > dimExprs.Length) { throw new ParseException("Too many subscripts", indexExprs[dimExprs.Length].Token); } else // indexExprs.Length == dimExprs.Length { /* | | | ind[0] dim[1] * ind[1] + dim[2] * ind[2] + dim[3] * ind[3] + */ Expr indexExpr = indexExprs[0]; for (int i = 1; i < indexExprs.Length; ++i) { int dim = Expr.EvaluateIntConstant(dimExprs[i]); indexExpr = new BinaryExpr(null, 0xf4, indexExpr, new IntExpr(null, dim)); // mul indexExpr = new BinaryExpr(null, 0xec, indexExpr, indexExprs[i]); // add } return indexExpr; } }
public override bool Std(out Stmt s) { s = null; if (this.Column != 0) throw new ParseException("CON must be in 1st column", this); Tokenizer.Advance(); // past "CON" if (Tokenizer.Current.Text == "(eol)") Tokenizer.Advance("(eol)"); Expr conOrgExpr = new IntExpr(new SimpleToken(Tokenizer, SimpleTokenType.IntLiteral, "0", 0, 0, 0), 0); while (true) { if (Tokenizer.Current.Text == "#") { Tokenizer.Advance("#"); conOrgExpr = ParseExpression(Tokenizer, 13); } else if (Tokenizer.Current is IdToken) { IdToken constantName = Tokenizer.GetToken() as IdToken; if (Tokenizer.Current.Text == "=") { Tokenizer.Advance("="); SymbolTable.AddConSymbol(constantName, ParseExpression(Tokenizer, 13)); } else { SymbolTable.AddConSymbol(constantName, conOrgExpr); if (Tokenizer.Current.Text == "[") { Tokenizer.Advance("["); Expr incrExpr = ParseExpression(Tokenizer, 13); Tokenizer.Advance("]"); conOrgExpr = new BinaryExpr( new SimpleToken(Tokenizer, SimpleTokenType.Op, "+", 0, 0), 666, // fake opcode conOrgExpr, incrExpr); } else { Expr incrExpr = new IntExpr(new SimpleToken(Tokenizer, SimpleTokenType.IntLiteral, "(1)", 0, 0, 1), 1); conOrgExpr = new BinaryExpr( new SimpleToken(Tokenizer, SimpleTokenType.Op, "+", 0, 0), 666, // fake opcode conOrgExpr, incrExpr); } } } else break; if (Tokenizer.Current.Text == ",") Tokenizer.Advance(","); else Tokenizer.Advance("(eol)"); } return true; }
public void Visit(BinaryExpr e) { FloInt r1 = Expr.EvaluateConstant(e.Operand1, insideDat); FloInt r2 = Expr.EvaluateConstant(e.Operand2, insideDat); if (r1.IsInt) { if (!r2.IsInt) throw new ParseException("Can't mix int and floating-point", e.Token); int i1 = r1.IntValue; int i2 = r2.IntValue; switch (e.Token.Text.ToUpper()) { case "->": result = new FloInt(Ror(i1, i2)); break; case "<-": result = new FloInt(Rol(i1, i2)); break; case ">>": result = new FloInt(Shr(i1, i2)); break; case "<<": result = new FloInt(i1 << i2); break; case "~>": result = new FloInt(Sar(i1, i2)); break; case "><": result = new FloInt(Rev(i1, i2)); break; case "&": result = new FloInt(i1 & i2); break; case "|": result = new FloInt(i1 | i2); break; case "^": result = new FloInt(i1 ^ i2); break; case "*": result = new FloInt(i1 * i2); break; case "**": result = new FloInt((int)(((long)i1 * (long)i2) >> 32)); break; case "/": result = new FloInt(i1 / i2); break; case "//": result = new FloInt(i1 % i2); break; case "+": result = new FloInt(i1 + i2); break; case "-": result = new FloInt(i1 - i2); break; case "#>": result = new FloInt(i1 > i2 ? i1 : i2); break; case "<#": result = new FloInt(i1 > i2 ? i2 : i1); break; case "<": result = new FloInt(i1 < i2 ? -1 : 0); break; case ">": result = new FloInt(i1 > i2 ? -1 : 0); break; case "<>": result = new FloInt(i1 != i2 ? -1 : 0); break; case "==": result = new FloInt(i1 == i2 ? -1 : 0); break; case "=<": result = new FloInt(i1 <= i2 ? -1 : 0); break; case "=>": result = new FloInt(i1 >= i2 ? -1 : 0); break; case "AND": result = new FloInt((i1 != 0) && (i2 != 0) ? -1 : 0); break; case "OR": result = new FloInt((i1 != 0) || (i2 != 0) ? -1 : 0); break; default: throw new ParseException("Bad operator in constant expression: " + e.Token.Text, e.Token); } } else // r1 is float { if (r2.IsInt) throw new ParseException("Can't mix int and floating-point", e.Token); float f1 = r1.FloatValue; float f2 = r2.FloatValue; switch (e.Token.Text.ToUpper()) { case "*": result = new FloInt(f1 * f2); break; case "/": result = new FloInt(f1 / f2); break; case "+": result = new FloInt(f1 + f2); break; case "-": result = new FloInt(f1 - f2); break; case "#>": result = new FloInt(f1 > f2 ? f1 : f2); break; case "<#": result = new FloInt(f1 > f2 ? f2 : f1); break; case "<": result = new FloInt(f1 < f2 ? 1.0f : 0.0f); break; case ">": result = new FloInt(f1 > f2 ? 1.0f : 0.0f); break; case "<>": result = new FloInt(f1 != f2 ? 1.0f : 0.0f); break; case "==": result = new FloInt(f1 == f2 ? 1.0f : 0.0f); break; case "=<": result = new FloInt(f1 <= f2 ? 1.0f : 0.0f); break; case "=>": result = new FloInt(f1 >= f2 ? 1.0f : 0.0f); break; case "AND": result = new FloInt((f1 != 0.0f) && (f2 != 0.0f) ? 1.0f : 0.0f); break; case "OR": result = new FloInt((f1 != 0.0f) || (f2 != 0.0f) ? 1.0f : 0.0f); break; default: throw new ParseException("Bad operator in constant expression: " + e.Token.Text, e.Token); } } }