Warning, /games/kmuddy/libs/bison-input.ypp is written in an unsupported language. File is not indexed.
0001 %{ 0002 /* 0003 Copyright 2005-2011 Tomas Mecir <kmuddy@kmuddy.com> 0004 Copyright 2005 Alex Bache <alexbache@ntlworld.com> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include <list> 0021 0022 #include "instructions.h" 0023 0024 using namespace std; 0025 0026 // Source code and destination for compiled instructions 0027 const char *source; 0028 bool new_source; 0029 list<instruction> *code; 0030 instruction op; 0031 0032 // Marker to notify of invalid characters in expression 0033 bool token_error; 0034 0035 // Functions required by Flex/Bison 0036 int yylex(void); 0037 void yyerror(const char *); 0038 0039 // Compile an expression into a list of instructions 0040 bool compile(const char *source_code, 0041 list<instruction> *compiled_code); 0042 0043 // Output an 'operation' instruction 0044 void make_op(instruction::instruction_type instr); 0045 0046 // Output an instruction with an integer operand 0047 void make_integer_op(instruction::instruction_type instr, 0048 const int operand); 0049 0050 // Output an instruction with a double operand 0051 void make_double_op(instruction::instruction_type instr, 0052 const double operand); 0053 0054 // Output an instruction with a string operand 0055 void make_string_op(instruction::instruction_type instr, 0056 char *operand); 0057 0058 %} 0059 0060 %union 0061 { 0062 int int_val; 0063 double double_val; 0064 char *string_val; 0065 int nothing; 0066 } 0067 0068 // Tokens - basic units we extract from input using Flex 0069 %token <int_val> INTEGER 0070 %token <double_val> DOUBLE_V 0071 %token <string_val> STRING_V 0072 %token <string_val> STRING_LITERAL 0073 %token <string_val> FUNCTION_NAME 0074 %token STRING_TYPECAST INT_TYPECAST DOUBLE_TYPECAST 0075 %token AND OR 0076 %token GT GE LT LE EQUALS NOT_EQUALS 0077 0078 // Define data types of nonterminal symbols 0079 %type <nothing> expr 0080 %type <string_val> func_call 0081 0082 // Operator precedence rules - describes which operations are done before others 0083 %left AND OR 0084 %left GT GE LT LE EQ NE 0085 %left '+' '-' '.' 0086 %left '*' '/' 0087 %nonassoc STRING_TYPECAST INT_TYPECAST DOUBLE_TYPECAST 0088 %left UMINUS '!' 0089 %right FUNCTION_CALL 0090 0091 %% 0092 expr: expr AND expr { make_op(instruction::and_op); } 0093 | expr OR expr { make_op(instruction::or_op); } 0094 | expr GT expr { make_op(instruction::greater_than); } 0095 | expr GE expr { make_op(instruction::greater_or_equal); } 0096 | expr LT expr { make_op(instruction::less_than); } 0097 | expr LE expr { make_op(instruction::less_or_equal); } 0098 | expr EQ expr { make_op(instruction::equals); } 0099 | expr NE expr { make_op(instruction::not_equal); } 0100 | expr '+' expr { make_op(instruction::add); } 0101 | expr '-' expr { make_op(instruction::sub); } 0102 | expr '*' expr { make_op(instruction::mult); } 0103 | expr '/' expr { make_op(instruction::div); } 0104 | expr '.' expr { make_op(instruction::string_concat); } 0105 | '(' expr ')' { } 0106 | func_call arg_list ')' %prec FUNCTION_CALL { make_string_op(instruction::function_call, $1); } 0107 ; 0108 0109 // generating expressions from basic tokens ... 0110 0111 expr: INTEGER { make_integer_op(instruction::push_value, $1); } 0112 | DOUBLE_V { make_double_op(instruction::push_value, $1); } 0113 | STRING_V { make_string_op(instruction::push_variable, $1); } 0114 | STRING_LITERAL { make_string_op(instruction::push_value, $1); } 0115 | '-' expr %prec UMINUS { make_op(instruction::unary_minus); } 0116 | '!' expr %prec '!' { make_op(instruction::not_op); } 0117 | INT_TYPECAST expr %prec INT_TYPECAST { make_op(instruction::cast_to_int); } 0118 | DOUBLE_TYPECAST expr %prec DOUBLE_TYPECAST { make_op(instruction::cast_to_double); } 0119 | STRING_TYPECAST expr %prec STRING_TYPECAST { make_op(instruction::cast_to_string); } 0120 ; 0121 0122 func_call: FUNCTION_NAME { make_op(instruction::push_func_arg_marker); } 0123 ; 0124 0125 arg_list: expr 0126 | arg_list ',' expr 0127 ; 0128 0129 0130 %% 0131 0132 //*************************************************************** 0133 // Function to handle errors (required by Bison) 0134 //*************************************************************** 0135 0136 void yyerror(const char *) 0137 { 0138 } // yyerror 0139 0140 0141 0142 //*************************************************************** 0143 // Function to compile source into a list of instructions using 0144 // Bison. 0145 // 0146 // Returns true if compiled successfully 0147 //*************************************************************** 0148 0149 bool compile(const char *source_code, 0150 list<instruction> *compiled_code) 0151 { 0152 source = source_code; 0153 new_source = true; 0154 code = compiled_code; 0155 token_error = false; 0156 0157 code->clear(); 0158 0159 if ((yyparse() == 0) && 0160 (token_error == false) ) 0161 { 0162 return true; 0163 } // endif compiled source successfully 0164 else 0165 { 0166 code->clear(); 0167 0168 return false; 0169 } // endelse failed to compile 0170 0171 } // compile 0172 0173 0174 0175 //*************************************************************** 0176 // Output an 'operation' instruction 0177 //*************************************************************** 0178 0179 void make_op(instruction::instruction_type instr) 0180 { 0181 op.instr = instr; 0182 op.arg = cValue::empty(); 0183 0184 code->push_back(op); 0185 0186 } // make_op 0187 0188 0189 0190 //*************************************************************** 0191 // Output an instruction with an integer operand 0192 //*************************************************************** 0193 0194 void make_integer_op(instruction::instruction_type instr, 0195 const int operand) 0196 { 0197 op.instr = instr; 0198 op.arg = cValue (operand); 0199 0200 code->push_back(op); 0201 0202 } // make_integer_op 0203 0204 0205 0206 //*************************************************************** 0207 // Output an instruction with a double operand 0208 //*************************************************************** 0209 0210 void make_double_op(instruction::instruction_type instr, 0211 const double operand) 0212 { 0213 op.instr = instr; 0214 op.arg = cValue (operand); 0215 0216 code->push_back(op); 0217 0218 } // make_double_op 0219 0220 0221 0222 //*************************************************************** 0223 // Output an instruction with a string operand 0224 //*************************************************************** 0225 0226 void make_string_op(instruction::instruction_type instr, 0227 char *operand) 0228 { 0229 op.instr = instr; 0230 op.arg = cValue (QString (operand)); 0231 0232 code->push_back(op); 0233 0234 } // make_string_op 0235