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