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