calculator.lemon
author Ryan C. Gordon <icculus@icculus.org>
Tue, 09 Feb 2010 00:08:12 -0500
branchcalculator-experiment
changeset 824 f4b3ba2b435d
parent 823 48757134a880
child 826 59a6a8aa7d87
permissions -rw-r--r--
"identifier" shouldn't be a non-terminal.

/**
 * MojoShader; generate shader programs from bytecode of compiled
 *  Direct3D shaders.
 *
 * Please see the file LICENSE.txt in the source's root directory.
 *
 *  This file written by Ryan C. Gordon.
 */

// This is a Lemon Parser grammar for HLSL. It is based on an ANSI C YACC
//  grammar by Jeff Lee: http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

// Lemon is here: http://www.hwaci.com/sw/lemon/  ...  the source is included
//  with MojoShader, and built with the library, so you don't have to track
//  down the dependency.

%name ParseCalculator

// Some shift-reduce conflicts are basically unavoidable, but if the final
//  conflict count matches this value, we consider it known and acceptable.
%expect 0

%start_symbol calculator
%token_prefix TOKEN_CALC_
%token_type { TokenData }
%extra_argument { Context *ctx }

%include {
#ifndef __MOJOSHADER_CALC_COMPILER__
#error Do not compile this file directly.
#endif
}

%syntax_error {
    fprintf(stderr,"Syntax error\n");
}

%parse_failure {
    ctx->isfail = 1;
    fprintf(stderr, "Giving up. Parser is hopelessly lost...\n");

}

%stack_overflow {
    ctx->isfail = 1;
    fprintf(stderr, "Giving up. Parser stack overflow\n");
}

// operator precedence (matches C spec)...

%left COMMA.
%right ASSIGN ADDASSIGN SUBASSIGN MULASSIGN DIVASSIGN MODASSIGN LSHIFTASSIGN
       RSHIFTASSIGN ANDASSIGN ORASSIGN XORASSIGN.
%right QUESTION.
%left OROR.
%left ANDAND.
%left OR.
%left XOR.
%left AND.
%left EQL NEQ.
%left LT LEQ GT GEQ.
%left LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH PERCENT.
%right TYPECAST EXCLAMATION COMPLEMENT MINUSMINUS PLUSPLUS.
%left DOT LBRACKET RBRACKET LPAREN RPAREN.

// bump up the precedence of ELSE, to avoid shift/reduce conflict on the
//  usual "dangling else ambiguity" ...
%right ELSE.


// The rules...

%type calculator { int }                // !!! FIXME: remove this later.
%destructor calculator { (void) ctx; }  // !!! FIXME: remove this later.
calculator ::= expression(B). { parse_complete(ctx, B); }

// the expression stuff is based on Jeff Lee's ANSI C grammar.
%type primary_expr { Expression * }
primary_expr(A) ::= IDENTIFIER(B). { A = new_identifier_expr(ctx, &B); }
primary_expr(A) ::= INT_CONSTANT(B). { A = new_literal_int_expr(ctx, &B); }
primary_expr(A) ::= FLOAT_CONSTANT(B). { A = new_literal_float_expr(ctx, &B); }
primary_expr(A) ::= STRING_LITERAL(B). { A = new_literal_string_expr(ctx, &B); }
primary_expr(A) ::= LPAREN expression(B) RPAREN. { A = B; }

%type postfix_expr { Expression * }
postfix_expr(A) ::= primary_expr(B). { A = B; }
postfix_expr(A) ::= postfix_expr(B) LBRACKET expression(C) RBRACKET. { A = new_binary_expr(ctx, OP_DEREF_ARRAY, B, C); }
postfix_expr(A) ::= postfix_expr(B) LPAREN RPAREN. { A = new_binary_expr(ctx, OP_CALLFUNC, B, NULL); }
postfix_expr(A) ::= postfix_expr(B) LPAREN argument_expr_list(C) RPAREN. { A = new_binary_expr(ctx, OP_CALLFUNC, B, C); }
//postfix_expr(A) ::= datatype(B) LPAREN argument_expr_list(C) RPAREN. { A = new_constructor_expr(ctx, B, C); } // HLSL constructor
postfix_expr(A) ::= postfix_expr(B) DOT IDENTIFIER(C). { A = new_binary_expr(ctx, OP_DEREF_STRUCT, B, new_identifier_expr(ctx, &C)); }
postfix_expr(A) ::= postfix_expr(B) PLUSPLUS. { A = new_unary_expr(ctx, OP_POSTINCREMENT, B); }
postfix_expr(A) ::= postfix_expr(B) MINUSMINUS. { A = new_unary_expr(ctx, OP_POSTDECREMENT, B); }

%type argument_expr_list { Expression * }
argument_expr_list(A) ::= assignment_expr(B). { A = B; }
argument_expr_list(A) ::= argument_expr_list(B) COMMA assignment_expr(C). { A = new_binary_expr(ctx, OP_COMMA, B, C); }

%type unary_expr { Expression * }
unary_expr(A) ::= postfix_expr(B).  { A = B; }
unary_expr(A) ::= PLUSPLUS unary_expr(B). { A = new_unary_expr(ctx, OP_PREINCREMENT, B); }
unary_expr(A) ::= MINUSMINUS unary_expr(B). { A = new_unary_expr(ctx, OP_PREDECREMENT, B); }
unary_expr(A) ::= PLUS cast_expr(B). { A = B; }  // unary "+x" is always a no-op, so throw it away here.
unary_expr(A) ::= MINUS cast_expr(B). { A = new_unary_expr(ctx, OP_NEGATE, B); }
unary_expr(A) ::= COMPLEMENT cast_expr(B). { A = new_unary_expr(ctx, OP_COMPLEMENT, B); }
unary_expr(A) ::= EXCLAMATION cast_expr(B). { A = new_unary_expr(ctx, OP_NOT, B); }

%type cast_expr { Expression * }
cast_expr(A) ::= unary_expr(B). { A = B; }
//cast_expr(A) ::= LPAREN datatype(B) RPAREN cast_expr(C). { A = new_cast_expr(ctx, B, C); }

%type multiplicative_expr { Expression * }
multiplicative_expr(A) ::= cast_expr(B). { A = B; }
multiplicative_expr(A) ::= multiplicative_expr(B) STAR cast_expr(C). { A = new_binary_expr(ctx, OP_MULTIPLY, B, C); }
multiplicative_expr(A) ::= multiplicative_expr(B) SLASH cast_expr(C). { A = new_binary_expr(ctx, OP_DIVIDE, B, C); }
multiplicative_expr(A) ::= multiplicative_expr(B) PERCENT cast_expr(C). { A = new_binary_expr(ctx, OP_MODULO, B, C); }

%type additive_expr { Expression * }
additive_expr(A) ::= multiplicative_expr(B). { A = B; }
additive_expr(A) ::= additive_expr(B) PLUS multiplicative_expr(C). { A = new_binary_expr(ctx, OP_ADD, B, C); }
additive_expr(A) ::= additive_expr(B) MINUS multiplicative_expr(C). { A = new_binary_expr(ctx, OP_SUBTRACT, B, C); }

%type shift_expr { Expression * }
shift_expr(A) ::= additive_expr(B). { A = B; }
shift_expr(A) ::= shift_expr(B) LSHIFT additive_expr(C). { A = new_binary_expr(ctx, OP_LSHIFT, B, C); }
shift_expr(A) ::= shift_expr(B) RSHIFT additive_expr(C). { A = new_binary_expr(ctx, OP_RSHIFT, B, C); }

%type relational_expr { Expression * }
relational_expr(A) ::= shift_expr(B). { A = B; }
relational_expr(A) ::= relational_expr(B) LT shift_expr(C). { A = new_binary_expr(ctx, OP_LESSTHAN, B, C); }
relational_expr(A) ::= relational_expr(B) GT shift_expr(C). { A = new_binary_expr(ctx, OP_GREATERTHAN, B, C); }
relational_expr(A) ::= relational_expr(B) LEQ shift_expr(C). { A = new_binary_expr(ctx, OP_LESSTHANOREQUAL, B, C); }
relational_expr(A) ::= relational_expr(B) GEQ shift_expr(C). { A = new_binary_expr(ctx, OP_GREATERTHANOREQUAL, B, C); }

%type equality_expr { Expression * }
equality_expr(A) ::= relational_expr(B). { A = B; }
equality_expr(A) ::= equality_expr(B) EQL relational_expr(C). { A = new_binary_expr(ctx, OP_EQUAL, B, C); }
equality_expr(A) ::= equality_expr(B) NEQ relational_expr(C). { A = new_binary_expr(ctx, OP_NOTEQUAL, B, C); }

%type and_expr { Expression * }
and_expr(A) ::= equality_expr(B). { A = B; }
and_expr(A) ::= and_expr(B) AND equality_expr(C). { A = new_binary_expr(ctx, OP_BINARYAND, B, C); }

%type exclusive_or_expr { Expression * }
exclusive_or_expr(A) ::= and_expr(B). { A = B; }
exclusive_or_expr(A) ::= exclusive_or_expr(B) XOR and_expr(C). { A = new_binary_expr(ctx, OP_BINARYXOR, B, C); }

%type inclusive_or_expr { Expression * }
inclusive_or_expr(A) ::= exclusive_or_expr(B). { A = B; }
inclusive_or_expr(A) ::= inclusive_or_expr(B) OR exclusive_or_expr(C). { A = new_binary_expr(ctx, OP_BINARYOR, B, C); }

%type logical_and_expr { Expression * }
logical_and_expr(A) ::= inclusive_or_expr(B). { A = B; }
logical_and_expr(A) ::= logical_and_expr(B) ANDAND inclusive_or_expr(C). { A = new_binary_expr(ctx, OP_LOGICALAND, B, C); }

%type logical_or_expr { Expression * }
logical_or_expr(A) ::= logical_and_expr(B). { A = B; }
logical_or_expr(A) ::= logical_or_expr(B) OROR logical_and_expr(C). { A = new_binary_expr(ctx, OP_LOGICALOR, B, C); }

%type conditional_expr { Expression * }
conditional_expr(A) ::= logical_or_expr(B). { A = B; }
conditional_expr(A) ::= logical_or_expr(B) QUESTION logical_or_expr(C) COLON conditional_expr(D). { A = new_ternary_expr(ctx, OP_CONDITIONAL, B, C, D); }

%type assignment_expr { Expression * }
assignment_expr(A) ::= conditional_expr(B). { A = B; }
assignment_expr(A) ::= unary_expr(B) ASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_ASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) MULASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_MULASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) DIVASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_DIVASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) MODASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_MODASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) ADDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_ADDASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) SUBASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_SUBASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) LSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_LSHIFTASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) RSHIFTASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_RSHIFTASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) ANDASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_ANDASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) XORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_XORASSIGN, B, C); }
assignment_expr(A) ::= unary_expr(B) ORASSIGN assignment_expr(C). { A = new_binary_expr(ctx, OP_ORASSIGN, B, C); }

%type expression { Expression * }
expression(A) ::= assignment_expr(B). { A = B; }
expression(A) ::= expression(B) COMMA assignment_expr(C). { A = new_binary_expr(ctx, OP_COMMA, B, C); }

// end of calculator.lemon ...