| /* |
| * expr_java.tc - Expression example treecc input file for Java. |
| * |
| * Copyright (C) 2001 Southern Storm Software, Pty Ltd. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| %option lang = "Java" |
| |
| /* |
| * Define the type code that is associated with a node |
| * in the syntax tree. We use "error_type" to indicate |
| * a failure during type inferencing. |
| */ |
| %enum type_code = |
| { |
| error_type, |
| int_type, |
| float_type |
| } |
| |
| /* |
| * Define the node types that make up the syntax. |
| */ |
| %node expression %abstract %typedef = |
| { |
| %nocreate type_code type = {type_code.error_type}; |
| } |
| |
| %node binary expression %abstract = |
| { |
| expression expr1; |
| expression expr2; |
| } |
| |
| %node unary expression %abstract = |
| { |
| expression expr; |
| } |
| |
| %node intnum expression = |
| { |
| int num; |
| } |
| |
| %node floatnum expression = |
| { |
| float num; |
| } |
| |
| %node plus binary |
| %node minus binary |
| %node multiply binary |
| %node divide binary |
| %node power binary |
| %node negate unary |
| |
| %node cast expression = |
| { |
| type_code new_type; |
| expression expr; |
| } |
| |
| /* |
| * Define the "infer_type" operation as a non-virtual. |
| */ |
| %operation void infer_type(expression e) |
| |
| infer_type(binary) |
| { |
| infer_type(e.expr1); |
| infer_type(e.expr2); |
| |
| if(e.expr1.type == type_code.error_type || |
| e.expr2.type == type_code.error_type) |
| { |
| e.type = type_code.error_type; |
| } |
| else if(e.expr1.type == type_code.float_type || |
| e.expr2.type == type_code.float_type) |
| { |
| e.type = type_code.float_type; |
| } |
| else |
| { |
| e.type = type_code.int_type; |
| } |
| } |
| |
| infer_type(unary) |
| { |
| infer_type(e.expr); |
| e.type = e.expr.type; |
| } |
| |
| infer_type(intnum) |
| { |
| e.type = type_code.int_type; |
| } |
| |
| infer_type(floatnum) |
| { |
| e.type = type_code.float_type; |
| } |
| |
| infer_type(power) |
| { |
| infer_type(e.expr1); |
| infer_type(e.expr2); |
| |
| if(e.expr1.type == type_code.error_type || |
| e.expr2.type == type_code.error_type) |
| { |
| e.type = type_code.error_type; |
| } |
| else if(e.expr2.type != type_code.int_type) |
| { |
| System.err.println(e.getFilename() + ":" + e.getLinenum() + |
| ": second argument to `^' is not an integer"); |
| e.type = type_code.error_type; |
| } |
| else |
| { |
| e.type = e.expr1.type; |
| } |
| } |
| |
| infer_type(cast) |
| { |
| infer_type(e.expr); |
| |
| if(e.expr.type != type_code.error_type) |
| { |
| e.type = e.new_type; |
| } |
| else |
| { |
| e.type = type_code.error_type; |
| } |
| } |
| |
| /* |
| * Define the "eval_expr" operation as a virtual. |
| */ |
| %operation %virtual eval_value eval_expr(expression *this) |
| |
| eval_expr(plus) |
| { |
| /* Evaluate the sub-expressions */ |
| eval_value value1 = expr1.eval_expr(); |
| eval_value value2 = expr2.eval_expr(); |
| |
| /* Coerce to the common type */ |
| coerce.coerce(value1, expr1.type, type); |
| coerce.coerce(value2, expr2.type, type); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| value1.int_value += value2.int_value; |
| } |
| else |
| { |
| value1.float_value += value2.float_value; |
| } |
| |
| /* Return the result to the caller */ |
| return value1; |
| } |
| |
| eval_expr(minus) |
| { |
| /* Evaluate the sub-expressions */ |
| eval_value value1 = expr1.eval_expr(); |
| eval_value value2 = expr2.eval_expr(); |
| |
| /* Coerce to the common type */ |
| coerce.coerce(value1, expr1.type, type); |
| coerce.coerce(value2, expr2.type, type); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| value1.int_value -= value2.int_value; |
| } |
| else |
| { |
| value1.float_value -= value2.float_value; |
| } |
| |
| /* Return the result to the caller */ |
| return value1; |
| } |
| |
| eval_expr(multiply) |
| { |
| /* Evaluate the sub-expressions */ |
| eval_value value1 = expr1.eval_expr(); |
| eval_value value2 = expr2.eval_expr(); |
| |
| /* Coerce to the common type */ |
| coerce.coerce(value1, expr1.type, type); |
| coerce.coerce(value2, expr2.type, type); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| value1.int_value *= value2.int_value; |
| } |
| else |
| { |
| value1.float_value *= value2.float_value; |
| } |
| |
| /* Return the result to the caller */ |
| return value1; |
| } |
| |
| eval_expr(divide) |
| { |
| /* Evaluate the sub-expressions */ |
| eval_value value1 = expr1.eval_expr(); |
| eval_value value2 = expr2.eval_expr(); |
| |
| /* Coerce to the common type */ |
| coerce.coerce(value1, expr1.type, type); |
| coerce.coerce(value2, expr2.type, type); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| if(value2.int_value != 0) |
| { |
| value1.int_value /= value2.int_value; |
| } |
| else |
| { |
| System.err.println(getFilename() + ":" + getLinenum() + |
| ": division by zero"); |
| value1.int_value = 0; |
| } |
| } |
| else |
| { |
| value1.float_value /= value2.float_value; |
| } |
| |
| /* Return the result to the caller */ |
| return value1; |
| } |
| |
| eval_expr(power) |
| { |
| /* Evaluate the sub-expressions */ |
| eval_value value1 = expr1.eval_expr(); |
| eval_value value2 = expr2.eval_expr(); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| value1.int_value = (int)(Math.pow((double)(value1.int_value), |
| (double)(value2.int_value))); |
| } |
| else |
| { |
| value1.float_value = (float)(Math.pow((double)(value1.float_value), |
| (double)(value2.int_value))); |
| } |
| |
| /* Return the result to the caller */ |
| return value1; |
| } |
| |
| eval_expr(negate) |
| { |
| /* Evaluate the sub-expression */ |
| eval_value value = expr.eval_expr(); |
| |
| /* Evaluate the operator */ |
| if(type == type_code.int_type) |
| { |
| value.int_value = -(value.int_value); |
| } |
| else |
| { |
| value.float_value = -(value.float_value); |
| } |
| |
| /* Return the result to the caller */ |
| return value; |
| } |
| |
| eval_expr(cast) |
| { |
| /* Evaluate the sub-expression */ |
| eval_value value = expr.eval_expr(); |
| |
| /* Cast to the final type */ |
| coerce.coerce(value, expr.type, type); |
| |
| /* Return the result to the caller */ |
| return value; |
| } |
| |
| eval_expr(intnum) |
| { |
| eval_value value = new eval_value(); |
| value.int_value = num; |
| return value; |
| } |
| |
| eval_expr(floatnum) |
| { |
| eval_value value = new eval_value(); |
| value.float_value = num; |
| return value; |
| } |
| |
| /* |
| * Define the "coerce" operation as an inline non-virtual. |
| */ |
| %operation %inline void coerce |
| (eval_value value, [type_code from], [type_code to]) |
| |
| coerce(int_type, float_type) |
| { |
| value.float_value = (float)(value.int_value); |
| } |
| |
| coerce(float_type, int_type) |
| { |
| value.int_value = (int)(value.float_value); |
| } |
| |
| coerce(type_code, type_code) |
| { |
| /* Nothing to do here */ |
| } |