private Expression boolOperatorCall(OperatorCall op, BoolValue val1, BoolValue val2) { if (op.op.Equals(ast.grammar.o["+"])) { return(new BoolValue(op, val1.value | val2.value)); } if (op.op.Equals(ast.grammar.o["-"])) { return(new BoolValue(op, val1.value & (!val2.value))); } if (op.op.Equals(ast.grammar.o["*"])) { return(new BoolValue(op, val1.value | val2.value)); } if (op.op.Equals(ast.grammar.o["&"])) { return(new BoolValue(op, val1.value & val2.value)); } if (op.op.Equals(ast.grammar.o["<"])) { return(new BoolValue(op, !val1.value && val2.value)); } if (op.op.Equals(ast.grammar.o["="])) { return(new BoolValue(op, val1.value == val2.value)); } if (op.op.Equals(new Operator("!"))) { return(new BoolValue(op, !val2.value)); } throw new ShouldntHappenException(op, "Unsupported operator for bool: " + op.op); }
private Expression operatorCall(OperatorCall node) { if (node.children.Count == 1) { return(unaryOperatorCall(node)); } if (node.children.Count == 2) { return(binaryOperatorCall(node)); } throw new ShouldntHappenException(node, "Operator call with " + node.children.Count + " operands"); }
private Expression stringOperatorCall(OperatorCall op, StringValue val1, StringValue val2) { if (op.op.Equals(ast.grammar.o["+"])) { return(new StringValue(op, val1.value + val2.value)); } if (op.op.Equals(ast.grammar.o["<"])) { return(new BoolValue(op, val1.value.CompareTo(val2.value) < 0)); } if (op.op.Equals(ast.grammar.o["="])) { return(new BoolValue(op, val1.value == val2.value)); } throw new ShouldntHappenException(op, "Unsupported operator for string: " + op.op); }
private Expression parseExpression(SyntaxNode node) { if (node.token.Equals(grammar.t["expr"])) { if (node.children[0].token.Equals(grammar.t["expr2"])) { return(parseExpression(node.children[0])); } if (node.children[0].token.Equals(grammar.t["unary_op"])) { OperatorCall ret = new OperatorCall(node); Expression operand = parseExpression(node.children[1]); ret.op = parseOperator(node.children[0]); if (!unaryOperatorMakesSense(ret.op, operand.type)) { addError(node, "Unary operator " + ret.op.ToString() + " can't be applied to " + operand.type); } ret.children.Add(operand); ret.type = operand.type; return(ret); } } if (node.token.Equals(grammar.t["opnd"])) { return(parseOperand(node)); } //node.token is expr2 if (node.children[1].children.Count > 0) { OperatorCall ret = new OperatorCall(node); ret.op = parseOperator(node.children[1].children[0]); ret.line = ret.op.line; ret.position = ret.op.position; Expression lhs = parseExpression(node.children[0]); Expression rhs = parseExpression(node.children[1].children[1]); if (!binaryOperatorMakesSense(ret.op, lhs.type, rhs.type)) { addError(node.children[1], "Binary operator " + ret.op.ToString() + " can't be applied to " + lhs.type + " and " + rhs.type); } ret.children.Add(lhs); ret.children.Add(rhs); ret.type = binaryOperatorResult(ret.op, lhs.type, rhs.type); return(ret); } return(parseExpression(node.children[0])); }
private Expression unaryOperatorCall(OperatorCall node) { Expression val = eval(node.children[0]); if (val is IntValue) { return(intOperatorCall(node, new IntValue(node, 0), (IntValue)val)); } if (val is StringValue) { return(stringOperatorCall(node, new StringValue(node, ""), (StringValue)val)); } if (val is BoolValue) { return(boolOperatorCall(node, new BoolValue(node, false), (BoolValue)val)); } throw new ShouldntHappenException(node, "Unknown type for calling operator"); }
private Expression binaryOperatorCall(OperatorCall node) { Expression val1 = eval(node.children[0]); Expression val2 = eval(node.children[1]); if (val1.type != val2.type) { throw new ShouldntHappenException(node, "Operator has different types"); } if (val1 is IntValue) { return(intOperatorCall(node, (IntValue)val1, (IntValue)val2)); } if (val1 is StringValue) { return(stringOperatorCall(node, (StringValue)val1, (StringValue)val2)); } if (val1 is BoolValue) { return(boolOperatorCall(node, (BoolValue)val1, (BoolValue)val2)); } throw new ShouldntHappenException(node, "Unknown type for calling operator"); }
private Expression intOperatorCall(OperatorCall op, IntValue val1, IntValue val2) { if (op.op.Equals(ast.grammar.o["+"])) { return(new IntValue(op, val1.value + val2.value)); } if (op.op.Equals(ast.grammar.o["-"])) { return(new IntValue(op, val1.value - val2.value)); } if (op.op.Equals(ast.grammar.o["*"])) { return(new IntValue(op, val1.value * val2.value)); } if (op.op.Equals(ast.grammar.o["/"])) { if (val2.value == 0) { throw new InterpreterException(op, "Division by zero"); } return(new IntValue(op, val1.value / val2.value)); } if (op.op.Equals(ast.grammar.o["&"])) { return(new IntValue(op, val1.value & val2.value)); } if (op.op.Equals(ast.grammar.o["<"])) { return(new BoolValue(op, val1.value < val2.value)); } if (op.op.Equals(ast.grammar.o["="])) { return(new BoolValue(op, val1.value == val2.value)); } throw new ShouldntHappenException(op, "Unsupported operator for int: " + op.op); }