From 963fd467cb86f75933f59e37709585689c89dcb0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Feb 2010 02:42:12 -0500 Subject: [PATCH] Start of experiment with a basic calculator. This is a throwaway so I can debug some of the HLSL parsing code, and get a better idea of what I want to do there. This will eventually merge back into the default branch with the right bits going into the compiler code. --HG-- branch : calculator-experiment --- CMakeLists.txt | 15 ++ calculator.c | 412 ++++++++++++++++++++++++++++++++++++++++++ calculator.lemon | 185 +++++++++++++++++++ mojoshader_internal.h | 4 + 4 files changed, 616 insertions(+) create mode 100644 calculator.c create mode 100644 calculator.lemon diff --git a/CMakeLists.txt b/CMakeLists.txt index bbc96151..8cf2476b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,21 @@ SET_SOURCE_FILES_PROPERTIES( PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/mojoshader_parser_hlsl.h" ) +# Calculator test stuff... +ADD_CUSTOM_COMMAND( + OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/calculator.h" + MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/calculator.lemon" + DEPENDS lemon "${CMAKE_CURRENT_SOURCE_DIR}/misc/lempar.c" + COMMAND "${LEMON}" + ARGS -q "-T${CMAKE_CURRENT_SOURCE_DIR}/misc/lempar.c" "${CMAKE_CURRENT_SOURCE_DIR}/calculator.lemon" +) +SET_SOURCE_FILES_PROPERTIES( + calculator.c + PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/calculator.h" +) +ADD_EXECUTABLE(calculator calculator.c) +TARGET_LINK_LIBRARIES(calculator mojoshader) + FIND_PROGRAM(RE2C re2c DOC "Path to re2c command line app: http://re2c.org/") IF(NOT RE2C) MESSAGE(STATUS "re2c missing. You can go on, but can't rebuild the lexer.") diff --git a/calculator.c b/calculator.c new file mode 100644 index 00000000..db01051e --- /dev/null +++ b/calculator.c @@ -0,0 +1,412 @@ +#define __MOJOSHADER_INTERNAL__ 1 +#include "mojoshader_internal.h" + +#if DEBUG_COMPILER_PARSER +#define LEMON_SUPPORT_TRACING 1 +#endif + +typedef struct Context +{ + int isfail; + int out_of_memory; + MOJOSHADER_malloc malloc; + MOJOSHADER_free free; + void *malloc_data; + int error_count; + ErrorList *errors; + Preprocessor *preprocessor; + const char *token; + unsigned int tokenlen; + Token tokenval; + unsigned int parse_errors; +} Context; + + +// Convenience functions for allocators... + +static inline void out_of_memory(Context *ctx) +{ + ctx->isfail = ctx->out_of_memory = 1; +} // out_of_memory + +static inline void *Malloc(Context *ctx, const size_t len) +{ + void *retval = ctx->malloc((int) len, ctx->malloc_data); + if (retval == NULL) + out_of_memory(ctx); + return retval; +} // Malloc + +static inline char *StrDup(Context *ctx, const char *str) +{ + char *retval = (char *) Malloc(ctx, strlen(str) + 1); + if (retval != NULL) + strcpy(retval, str); + return retval; +} // StrDup + +static inline void Free(Context *ctx, void *ptr) +{ + if (ptr != NULL) // check for NULL in case of dumb free() impl. + ctx->free(ptr, ctx->malloc_data); +} // Free + +typedef enum Operator +{ + OP_DEREF_ARRAY, + OP_CALLFUNC, + OP_DEREF_STRUCT, + OP_POSTINCREMENT, + OP_POSTDECREMENT, + OP_COMMA, + OP_PREINCREMENT, + OP_PREDECREMENT, + OP_NEGATE, + OP_COMPLEMENT, + OP_NOT, + OP_MULTIPLY, + OP_DIVIDE, + OP_MODULO, + OP_ADD, + OP_SUBTRACT, + OP_LSHIFT, + OP_RSHIFT, + OP_LESSTHAN, + OP_GREATERTHAN, + OP_LESSTHANOREQUAL, + OP_GREATERTHANOREQUAL, + OP_EQUAL, + OP_NOTEQUAL, + OP_BINARYAND, + OP_BINARYXOR, + OP_BINARYOR, + OP_LOGICALAND, + OP_LOGICALOR, + OP_CONDITIONAL, + OP_ASSIGN, + OP_MULASSIGN, + OP_DIVASSIGN, + OP_MODASSIGN, + OP_ADDASSIGN, + OP_SUBASSIGN, + OP_LSHIFTASSIGN, + OP_RSHIFTASSIGN, + OP_ANDASSIGN, + OP_XORASSIGN, + OP_ORASSIGN, +} Operator; + +typedef struct Expression +{ + Operator op; // operator +} Expression; + +#define NEW_EXPR(cls) \ + cls *retval = Malloc(ctx, sizeof (cls)); \ + if (retval == NULL) { return NULL; } + +typedef struct ExpressionUnary +{ + Operator op; // operator + Expression *operand; +} ExpressionUnary; + +typedef struct ExpressionBinary +{ + Operator op; // operator + Expression *left; + Expression *right; +} ExpressionBinary; + +typedef struct ExpressionTernary +{ + Operator op; // operator + Expression *left; + Expression *center; + Expression *right; +} ExpressionTernary; + +typedef struct ExpressionIdentifier +{ + Operator op; // Always TOKEN_CALC_IDENTIFIER + const char *identifier; +} ExpressionIdentifier; + +typedef struct ExpressionLiteralInt +{ + Operator op; // Always TOKEN_CALC_INT_CONSTANT + int64 value; +} ExpressionLiteralInt; + +typedef struct ExpressionLiteralFloat +{ + Operator op; // Always TOKEN_CALC_FLOAT_CONSTANT + double value; +} ExpressionLiteralFloat; + +typedef struct ExpressionLiteralString +{ + Operator op; // Always TOKEN_CALC_STRING_LITERAL + const char *string; +} ExpressionLiteralString; + +static const char *new_identifier(Context *); +static Expression *new_unary_expr(Context *, const Operator, Expression *); +static Expression *new_binary_expr(Context *, const Operator, Expression *, Expression *); +static Expression *new_ternary_expr(Context *, const Operator, Expression *, Expression *, Expression *); +static Expression *new_identifier_expr(Context *, const char *); +static Expression *new_literal_int_expr(Context *); +static Expression *new_literal_float_expr(Context *); +static Expression *new_literal_string_expr(Context *); + +static void parse_complete(const Expression *expr) +{ + printf("parse complete!\n"); + +} // parse_complete + + +// This is where the actual parsing happens. It's Lemon-generated! +#define __MOJOSHADER_CALC_COMPILER__ 1 +#include "calculator.h" + +static const char *new_identifier(Context *ctx) +{ + // !!! FIXME: this needs to cache strings. + const unsigned int len = ctx->tokenlen; + char *retval = Malloc(ctx, len + 1); + if (retval == NULL) + return NULL; + memcpy(retval, ctx->token, len); + retval[len] = '\0'; + return retval; +} // new_identifier + +static Expression *new_unary_expr(Context *ctx, const Operator op, + Expression *operand) +{ + NEW_EXPR(ExpressionUnary); + retval->op = op; + retval->operand = operand; + return (Expression *) retval; +} // new_unary_expr + +static Expression *new_binary_expr(Context *ctx, const Operator op, + Expression *left, Expression *right) +{ + NEW_EXPR(ExpressionBinary); + retval->op = op; + retval->left = left; + retval->right = right; + return (Expression *) retval; +} // new_binary_expr + +static Expression *new_ternary_expr(Context *ctx, const Operator op, + Expression *left, Expression *center, + Expression *right) +{ + NEW_EXPR(ExpressionTernary); + retval->op = op; + retval->left = left; + retval->center = center; + retval->right = right; + return (Expression *) retval; +} // new_ternary_expr + +static Expression *new_identifier_expr(Context *ctx, const char *identifier) +{ + NEW_EXPR(ExpressionIdentifier); + retval->op = TOKEN_CALC_IDENTIFIER; + retval->identifier = identifier; + return (Expression *) retval; +} // new_identifier_expr + +static inline int64 strtoi64(const char *str, unsigned int len) +{ + int64 retval = 0; + int64 mult = 1; + int i = 0; + + while ((len) && (*str == ' ')) + { + str++; + len--; + } // while + + if ((len) && (*str == '-')) + { + mult = -1; + str++; + len--; + } // if + + while (i < len) + { + const char ch = str[i]; + if ((ch < '0') || (ch > '9')) + break; + i++; + } // while + + while (--i >= 0) + { + const char ch = str[i]; + retval += ((int64) (ch - '0')) * mult; + mult *= 10; + } // while + + return retval; +} // strtoi64 + +static Expression *new_literal_int_expr(Context *ctx) +{ + NEW_EXPR(ExpressionLiteralInt); + retval->op = TOKEN_CALC_INT_CONSTANT; + retval->value = strtoi64(ctx->token, ctx->tokenlen); + return (Expression *) retval; +} // new_literal_int_expr + +static inline double strtodouble(const char *_str, unsigned int len) +{ + // !!! FIXME: laziness prevails. + char *str = (char *) alloca(len+1); + memcpy(str, _str, len); + str[len] = '\0'; + return strtod(str, NULL); +} // strtodouble + +static Expression *new_literal_float_expr(Context *ctx) +{ + NEW_EXPR(ExpressionLiteralFloat); + retval->op = TOKEN_CALC_FLOAT_CONSTANT; + retval->value = strtodouble(ctx->token, ctx->tokenlen); + return (Expression *) retval; +} // new_literal_float_expr + +static Expression *new_literal_string_expr(Context *ctx) +{ + NEW_EXPR(ExpressionLiteralString); + retval->op = TOKEN_CALC_STRING_LITERAL; + retval->string = new_identifier(ctx); + return (Expression *) retval; +} // new_string_literal_expr + + +static int convert_to_lemon_token(const Context *ctx) +{ + switch (ctx->tokenval) + { + case ((Token) ','): return TOKEN_CALC_COMMA; + case ((Token) '='): return TOKEN_CALC_ASSIGN; + case ((Token) TOKEN_ADDASSIGN): return TOKEN_CALC_ADDASSIGN; + case ((Token) TOKEN_SUBASSIGN): return TOKEN_CALC_SUBASSIGN; + case ((Token) TOKEN_MULTASSIGN): return TOKEN_CALC_MULASSIGN; + case ((Token) TOKEN_DIVASSIGN): return TOKEN_CALC_DIVASSIGN; + case ((Token) TOKEN_MODASSIGN): return TOKEN_CALC_MODASSIGN; + case ((Token) TOKEN_LSHIFTASSIGN): return TOKEN_CALC_LSHIFTASSIGN; + case ((Token) TOKEN_RSHIFTASSIGN): return TOKEN_CALC_RSHIFTASSIGN; + case ((Token) TOKEN_ANDASSIGN): return TOKEN_CALC_ANDASSIGN; + case ((Token) TOKEN_ORASSIGN): return TOKEN_CALC_ORASSIGN; + case ((Token) TOKEN_XORASSIGN): return TOKEN_CALC_XORASSIGN; + case ((Token) '?'): return TOKEN_CALC_QUESTION; + case ((Token) TOKEN_OROR): return TOKEN_CALC_OROR; + case ((Token) TOKEN_ANDAND): return TOKEN_CALC_ANDAND; + case ((Token) '|'): return TOKEN_CALC_OR; + case ((Token) '^'): return TOKEN_CALC_XOR; + case ((Token) '&'): return TOKEN_CALC_AND; + case ((Token) TOKEN_EQL): return TOKEN_CALC_EQL; + case ((Token) TOKEN_NEQ): return TOKEN_CALC_NEQ; + case ((Token) '<'): return TOKEN_CALC_LT; + case ((Token) TOKEN_LEQ): return TOKEN_CALC_LEQ; + case ((Token) '>'): return TOKEN_CALC_GT; + case ((Token) TOKEN_GEQ): return TOKEN_CALC_GEQ; + case ((Token) TOKEN_LSHIFT): return TOKEN_CALC_LSHIFT; + case ((Token) TOKEN_RSHIFT): return TOKEN_CALC_RSHIFT; + case ((Token) '+'): return TOKEN_CALC_PLUS; + case ((Token) '-'): return TOKEN_CALC_MINUS; + case ((Token) '*'): return TOKEN_CALC_STAR; + case ((Token) '/'): return TOKEN_CALC_SLASH; + case ((Token) '%'): return TOKEN_CALC_PERCENT; + case ((Token) '!'): return TOKEN_CALC_EXCLAMATION; + case ((Token) '~'): return TOKEN_CALC_COMPLEMENT; + case ((Token) TOKEN_DECREMENT): return TOKEN_CALC_MINUSMINUS; + case ((Token) TOKEN_INCREMENT): return TOKEN_CALC_PLUSPLUS; + case ((Token) '.'): return TOKEN_CALC_DOT; + case ((Token) '['): return TOKEN_CALC_LBRACKET; + case ((Token) ']'): return TOKEN_CALC_RBRACKET; + case ((Token) '('): return TOKEN_CALC_LPAREN; + case ((Token) ')'): return TOKEN_CALC_RPAREN; + case ((Token) TOKEN_INT_LITERAL): return TOKEN_CALC_INT_CONSTANT; + case ((Token) TOKEN_FLOAT_LITERAL): return TOKEN_CALC_FLOAT_CONSTANT; + case ((Token) TOKEN_STRING_LITERAL): return TOKEN_CALC_STRING_LITERAL; + case ((Token) ':'): return TOKEN_CALC_COLON; + //case ((Token) ';'): return TOKEN_CALC_SEMICOLON; + //case ((Token) '{'): return TOKEN_CALC_LBRACE; + //case ((Token) '}'): return TOKEN_CALC_RBRACE; + case ((Token) TOKEN_IDENTIFIER): return TOKEN_CALC_IDENTIFIER; + case TOKEN_EOI: return 0; + case TOKEN_BAD_CHARS: printf("bad chars from lexer\n"); return 0; + case TOKEN_PREPROCESSING_ERROR: printf("error from lexer\n"); return 0; + default: assert(0 && "unexpected token from lexer\n"); return 0; + } // switch + + return 0; +} // convert_to_lemon_token + +static void MOJOSHADER_compile(const char *filename, + const char *source, unsigned int sourcelen, + const MOJOSHADER_preprocessorDefine *defines, + unsigned int define_count, + MOJOSHADER_includeOpen include_open, + MOJOSHADER_includeClose include_close, + MOJOSHADER_malloc m, MOJOSHADER_free f, void *d) +{ + Context ctx; + if (m == NULL) m = MOJOSHADER_internal_malloc; + if (f == NULL) f = MOJOSHADER_internal_free; + + memset(&ctx, '\0', sizeof (Context)); + ctx.malloc = m; + ctx.free = f; + ctx.malloc_data = d; + ctx.preprocessor = preprocessor_start(filename, source, sourcelen, + include_open, include_close, + defines, define_count, 0, m, f, d); + + void *pParser = ParseCalculatorAlloc(m, d); + + #if DEBUG_COMPILER_PARSER + ParseCalculatorTrace(stdout, "COMPILER: "); + #endif + + do { + ctx.token = preprocessor_nexttoken(ctx.preprocessor, + &ctx.tokenlen, + &ctx.tokenval); + ParseCalculator(pParser, convert_to_lemon_token(&ctx), 0, &ctx); + } while (ctx.tokenval != TOKEN_EOI); + ParseCalculatorFree(pParser, f, d); +} + +int main(int argc, char **argv) +{ + const char *ln; + size_t len = 0; + FILE *io = stdin; + const char *filename = ""; + + while ((ln = fgetln(io, &len)) != NULL) + { + if ((len == 5) && (memcmp(ln, "quit\n", 5) == 0)) + break; + + MOJOSHADER_compile(filename, ln, (unsigned int) len, + NULL, 0, NULL, NULL, NULL, NULL, NULL); + } // while + + fclose(io); + return 0; +} // main + +// end of calculator.c ... + diff --git a/calculator.lemon b/calculator.lemon new file mode 100644 index 00000000..69da912f --- /dev/null +++ b/calculator.lemon @@ -0,0 +1,185 @@ +/** + * 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 { int } +%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 { + fprintf(stderr,"Giving up. Parser is hopelessly lost...\n"); +} + +%stack_overflow { + 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 { Expression * } +calculator(A) ::= expression(B). { A = B; } + +%type identifier { const char * } +%destructor identifier { (void) ctx; } // !!! FIXME: remove this later, it's just to shut up the compiler for now. +identifier(A) ::= IDENTIFIER. { A = new_identifier(ctx); } + +// 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. { A = new_literal_int_expr(ctx); } +primary_expr(A) ::= FLOAT_CONSTANT. { A = new_literal_float_expr(ctx); } +primary_expr(A) ::= STRING_LITERAL. { A = new_literal_string_expr(ctx); } +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 ... + diff --git a/mojoshader_internal.h b/mojoshader_internal.h index c81d5de2..bfd870eb 100644 --- a/mojoshader_internal.h +++ b/mojoshader_internal.h @@ -88,7 +88,9 @@ typedef unsigned int uint; // this is a printf() helper. don't use for code. typedef unsigned __int8 uint8; typedef unsigned __int16 uint16; typedef unsigned __int32 uint32; +typedef unsigned __int64 uint64; typedef __int32 int32; +typedef __int64 int64; // Warning Level 4 considered harmful. :) #pragma warning(disable: 4100) // "unreferenced formal parameter" #pragma warning(disable: 4389) // "signed/unsigned mismatch" @@ -98,6 +100,8 @@ typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef int32_t int32; +typedef int64_t int64; +typedef uint64_t uint64; #endif #ifdef sun