/*
 * Mesa 3-D graphics library
 * Version:  6.6
 *
 * Copyright (C) 2006  Brian Paul   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * \file slang_pp_expression.syn
 * slang preprocessor expression parser
 * \author Michal Krol
 */

/*
 * Parses one or two (optional) expressions on literal integer constants. Those expressions come
 * from #if #elif and #line directives. The preprocessor already parsed those directives and
 * expanded the expression (expressions). All occurences of the operator "defined" are already
 * replaced with either "0" or "1" literals.
 */

.syntax expression;

/*
 * Those separate individual expressions.
 * For #if/#elif case it is: EXP_EXPRESSION ... EXP_END
 * For #line case it may be: EXP_EXPRESSION ... EXP_EXPRESSION ... EXP_END
 */
.emtcode EXP_END        0
.emtcode EXP_EXPRESSION 1

.emtcode OP_END          0
.emtcode OP_PUSHINT      1
.emtcode OP_LOGICALOR    2
.emtcode OP_LOGICALAND   3
.emtcode OP_OR           4
.emtcode OP_XOR          5
.emtcode OP_AND          6
.emtcode OP_EQUAL        7
.emtcode OP_NOTEQUAL     8
.emtcode OP_LESSEQUAL    9
.emtcode OP_GREATEREQUAL 10
.emtcode OP_LESS         11
.emtcode OP_GREATER      12
.emtcode OP_LEFTSHIFT    13
.emtcode OP_RIGHTSHIFT   14
.emtcode OP_ADD          15
.emtcode OP_SUBTRACT     16
.emtcode OP_MULTIPLY     17
.emtcode OP_DIVIDE       18
.emtcode OP_MODULUS      19
.emtcode OP_PLUS         20
.emtcode OP_MINUS        21
.emtcode OP_NEGATE       22
.emtcode OP_COMPLEMENT   23

expression
   first_expression .and optional_second_expression .and optional_space .and '\0' .emit EXP_END;

first_expression
   optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;

optional_second_expression
   second_expression .or .true;

second_expression
   space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;

logical_or_expression
   logical_and_expression .and .loop logical_or_expression_1;
logical_or_expression_1
   barbar .and logical_and_expression .and .true .emit OP_LOGICALOR;

logical_and_expression
   or_expression .and .loop logical_and_expression_1;
logical_and_expression_1
   ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND;

or_expression
   xor_expression .and .loop or_expression_1;
or_expression_1
   bar .and xor_expression .and .true .emit OP_OR;

xor_expression
    and_expression .and .loop xor_expression_1;
xor_expression_1
    caret .and and_expression .and .true .emit OP_XOR;

and_expression
    equality_expression .and .loop and_expression_1;
and_expression_1
    ampersand .and equality_expression .and .true .emit OP_AND;

equality_expression
    relational_expression .and .loop equality_expression_1;
equality_expression_1
    equality_expression_2 .or equality_expression_3;
equality_expression_2
    equalsequals .and relational_expression .and .true .emit OP_EQUAL;
equality_expression_3
    bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;

relational_expression
    shift_expression .and .loop relational_expression_1;
relational_expression_1
    relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or
    relational_expression_5;
relational_expression_2
    lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;
relational_expression_3
    greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;
relational_expression_4
    less .and shift_expression .and .true .emit OP_LESS;
relational_expression_5
    greater .and shift_expression .and .true .emit OP_GREATER;

shift_expression
    additive_expression .and .loop shift_expression_1;
shift_expression_1
    shift_expression_2 .or shift_expression_3;
shift_expression_2
    lessless .and additive_expression .and .true .emit OP_LEFTSHIFT;
shift_expression_3
    greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT;

additive_expression
    multiplicative_expression .and .loop additive_expression_1;
additive_expression_1
    additive_expression_2 .or additive_expression_3;
additive_expression_2
    plus .and multiplicative_expression .and .true .emit OP_ADD;
additive_expression_3
    dash .and multiplicative_expression .and .true .emit OP_SUBTRACT;

multiplicative_expression
    unary_expression .and .loop multiplicative_expression_1;
multiplicative_expression_1
    multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4;
multiplicative_expression_2
    star .and unary_expression .and .true .emit OP_MULTIPLY;
multiplicative_expression_3
    slash .and unary_expression .and .true .emit OP_DIVIDE;
multiplicative_expression_4
    percent .and unary_expression .and .true .emit OP_MODULUS;

unary_expression
    primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or
    unary_expression_4;
unary_expression_1
    plus .and unary_expression .and .true .emit OP_PLUS;
unary_expression_2
    dash .and unary_expression .and .true .emit OP_MINUS;
unary_expression_3
    bang .and unary_expression .and .true .emit OP_NEGATE;
unary_expression_4
    tilda .and unary_expression .and .true .emit OP_COMPLEMENT;

primary_expression
   intconstant .or primary_expression_1;
primary_expression_1
   lparen .and logical_or_expression .and rparen;

intconstant
   integer .emit OP_PUSHINT;

integer
   integer_dec;

integer_dec
   digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0';

digit_dec
   '0'-'9';

optional_space
   .loop single_space;

space
   single_space .and .loop single_space;

single_space
   ' ' .or '\t';

ampersand
   optional_space .and '&' .and optional_space;

ampersandampersand
   optional_space .and '&' .and '&' .and optional_space;

bang
   optional_space .and '!' .and optional_space;

bangequals
   optional_space .and '!' .and '=' .and optional_space;

bar
   optional_space .and '|' .and optional_space;

barbar
   optional_space .and '|' .and '|' .and optional_space;

caret
   optional_space .and '^' .and optional_space;

dash
   optional_space .and '-' .and optional_space;

equalsequals
   optional_space .and '=' .and '=' .and optional_space;

greater
   optional_space .and '>' .and optional_space;

greaterequals
   optional_space .and '>' .and '=' .and optional_space;

greatergreater
   optional_space .and '>' .and '>' .and optional_space;

less
   optional_space .and '<' .and optional_space;

lessequals
   optional_space .and '<' .and '=' .and optional_space;

lessless
   optional_space .and '<' .and '<' .and optional_space;

lparen
   optional_space .and '(' .and optional_space;

percent
   optional_space .and '%' .and optional_space;

plus
   optional_space .and '+' .and optional_space;

rparen
   optional_space .and ')' .and optional_space;

slash
   optional_space .and '/' .and optional_space;

star
   optional_space .and '*' .and optional_space;

tilda
   optional_space .and '~' .and optional_space;