mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 21:21:14 +00:00
1341 lines
35 KiB
Text
1341 lines
35 KiB
Text
/*
|
|
glsl-parse.y
|
|
|
|
parser for GLSL
|
|
|
|
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
Date: 2023/11/25
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
%define api.prefix {glsl_yy}
|
|
%define api.pure full
|
|
%define api.push-pull push
|
|
%define api.token.prefix {GLSL_}
|
|
%locations
|
|
%parse-param {void *scanner}
|
|
%define api.value.type {rua_val_t}
|
|
%define api.location.type {rua_loc_t}
|
|
|
|
%{
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#ifdef HAVE_STRINGS_H
|
|
# include <strings.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
|
|
#include <QF/hash.h>
|
|
#include <QF/sys.h>
|
|
#include <QF/va.h>
|
|
|
|
#define GLSL_YYDEBUG 1
|
|
#define GLSL_YYERROR_VERBOSE 1
|
|
#undef GLSL_YYERROR_VERBOSE
|
|
|
|
#include "tools/qfcc/include/algebra.h"
|
|
#include "tools/qfcc/include/attribute.h"
|
|
#include "tools/qfcc/include/class.h"
|
|
#include "tools/qfcc/include/debug.h"
|
|
#include "tools/qfcc/include/def.h"
|
|
#include "tools/qfcc/include/diagnostic.h"
|
|
#include "tools/qfcc/include/emit.h"
|
|
#include "tools/qfcc/include/expr.h"
|
|
#include "tools/qfcc/include/function.h"
|
|
#include "tools/qfcc/include/method.h"
|
|
#include "tools/qfcc/include/options.h"
|
|
#include "tools/qfcc/include/qfcc.h"
|
|
#include "tools/qfcc/include/reloc.h"
|
|
#include "tools/qfcc/include/rua-lang.h"
|
|
#include "tools/qfcc/include/shared.h"
|
|
#include "tools/qfcc/include/strpool.h"
|
|
#include "tools/qfcc/include/struct.h"
|
|
#include "tools/qfcc/include/switch.h"
|
|
#include "tools/qfcc/include/symtab.h"
|
|
#include "tools/qfcc/include/type.h"
|
|
#include "tools/qfcc/include/value.h"
|
|
|
|
#include "tools/qfcc/source/glsl-parse.h"
|
|
|
|
#define glsl_yytext qc_yyget_text (scanner)
|
|
char *qc_yyget_text (void *scanner);
|
|
|
|
static void
|
|
yyerror (YYLTYPE *yylloc, void *scanner, const char *s)
|
|
{
|
|
#ifdef GLSL_YYERROR_VERBOSE
|
|
error (0, "%s %s\n", glsl_yytext, s);
|
|
#else
|
|
error (0, "%s before %s", s, glsl_yytext);
|
|
#endif
|
|
}
|
|
|
|
static void __attribute__((used))
|
|
parse_error (void *scanner)
|
|
{
|
|
error (0, "parse error before %s", glsl_yytext);
|
|
}
|
|
|
|
#define PARSE_ERROR do { parse_error (scanner); YYERROR; } while (0)
|
|
|
|
#define first_line line
|
|
#define first_column column
|
|
|
|
int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
|
|
|
%}
|
|
|
|
%code requires { #define glsl_yypstate rua_yypstate }
|
|
|
|
// these tokens are common between qc and qp
|
|
%left LOW
|
|
%nonassoc IFX
|
|
%nonassoc ELSE
|
|
%nonassoc BREAK_PRIMARY
|
|
%nonassoc ';'
|
|
%nonassoc CLASS_NOT_CATEGORY
|
|
%nonassoc STORAGEX
|
|
|
|
%left COMMA
|
|
%right <op> '=' ASX
|
|
%right '?' ':'
|
|
%left OR
|
|
%left XOR
|
|
%left AND
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left EQ NE
|
|
%left LT GT GE LE
|
|
%token NAND NOR XNOR
|
|
// end of tokens common between qc and qp
|
|
|
|
%left SHL SHR
|
|
%left '+' '-'
|
|
%left '*' '/' '%' MOD SCALE GEOMETRIC QMUL QVMUL VQMUL
|
|
%left HADAMARD CROSS DOT WEDGE REGRESSIVE
|
|
%right <op> SIZEOF UNARY INCOP REVERSE STAR DUAL UNDUAL
|
|
%left HYPERUNARY
|
|
%left '.' '(' '['
|
|
|
|
%token <expr> VALUE STRING TOKEN
|
|
%token ELLIPSIS
|
|
%token RESERVED
|
|
// end of common tokens
|
|
|
|
%token <symbol> IDENTIFIER
|
|
|
|
%token WHILE DO IF ELSE FOR BREAK CONTINUE
|
|
%token RETURN
|
|
%token SWITCH CASE DEFAULT
|
|
%token <op> STRUCT
|
|
%token <spec> TYPE_SPEC TYPE_NAME TYPE_QUAL VOID
|
|
|
|
%token <spec> PRECISION INVARIANT SMOOTH FLAT NOPERSPECTIVE LAYOUT SHARED
|
|
%token <spec> PRECISE CONST IN OUT INOUT CENTROID PATCH SAMPLE UNIFORM BUFFER VOLATILE
|
|
%token <spec> RESTRICT READONLY WRITEONLY HIGH_PRECISION MEDIUM_PRECISION
|
|
%token <spec> LOW_PRECISION DISCARD COHERENT
|
|
|
|
%type <symbol> variable_identifier
|
|
%type <expr> expression primary_exprsssion assignment_expression
|
|
%type <expr> for_init_statement conditionopt expressionopt else
|
|
%type <expr> conditional_expression unary_expression postfix_expression
|
|
%type <expr> function_call function_call_or_method function_call_generic
|
|
%type <expr> function_call_header_with_parameters
|
|
%type <expr> function_call_header_no_parameters
|
|
%type <expr> function_call_header function_identifier
|
|
%type <expr> logical_or_expression logical_xor_expression
|
|
%type <expr> logical_and_expression
|
|
%type <expr> inclusive_or_expression exclusive_or_expression and_expression
|
|
%type <expr> equality_expression relational_expression
|
|
%type <expr> shift_expression additive_expression multiplicative_expression
|
|
%type <expr> integer_expression
|
|
%type <expr> initializer
|
|
%type <expr> condition
|
|
%type <expr> compound_statement_no_new_scope compound_statement
|
|
%type <expr> statement statement_no_new_scope statement_list
|
|
%type <expr> simple_statement expression_statement
|
|
%type <expr> declaration_statement selection_statement
|
|
%type <expr> switch_statement switch_statement_list case_label
|
|
%type <switch_block> switch_block
|
|
%type <expr> iteration_statement jump_statement
|
|
%type <expr> break_label continue_label
|
|
%type <mut_expr> initializer_list
|
|
%type <op> unary_operator assignment_operator
|
|
|
|
%type <spec> function_prototype function_declarator
|
|
%type <spec> function_header function_header_with_parameters
|
|
%type <spec> fully_specified_type type_specifier struct_specifier
|
|
%type <spec> type_qualifier single_type_qualifier type_specifier_nonarray
|
|
%type <spec> precision_qualifier interpolation_qualifier invariant_qualifier
|
|
%type <spec> precise_qualifer storage_qualifier layout_qualifier
|
|
|
|
%type <size> array_size
|
|
%type <type> array_specifier
|
|
|
|
%type <param> parameter_declaration
|
|
%type <param> parameter_declarator parameter_type_specifier
|
|
|
|
%{
|
|
|
|
static switch_block_t *switch_block;
|
|
static const expr_t *break_label;
|
|
static const expr_t *continue_label;
|
|
|
|
static symbol_t *
|
|
function_sym_type (specifier_t spec, symbol_t *sym)
|
|
{
|
|
sym->type = append_type (spec.sym->type, spec.type);
|
|
set_func_type_attrs (sym->type, spec);
|
|
sym->type = find_type (sym->type);
|
|
return sym;
|
|
}
|
|
|
|
|
|
%}
|
|
|
|
%expect 0
|
|
|
|
%%
|
|
|
|
translation_unit
|
|
: external_declaration
|
|
| translation_unit external_declaration
|
|
;
|
|
|
|
external_declaration
|
|
: function_definition
|
|
| declaration
|
|
| ';'
|
|
;
|
|
|
|
function_definition
|
|
: function_prototype
|
|
{
|
|
$<symtab>$ = current_symtab;
|
|
auto spec = $1;
|
|
spec.sym->type = parse_params (spec.sym->type, spec.params);
|
|
auto sym = function_sym_type (spec, spec.sym);
|
|
sym->params = spec.params;
|
|
sym = function_symbol (sym, true, true);
|
|
current_func = begin_function (sym, nullptr, current_symtab,
|
|
false, spec.storage);
|
|
current_symtab = current_func->locals;
|
|
current_storage = sc_local;
|
|
}
|
|
compound_statement_no_new_scope
|
|
{
|
|
auto spec = $1;
|
|
auto sym = spec.sym;
|
|
build_code_function (sym, nullptr, (expr_t *) $3);
|
|
current_symtab = $<symtab>2;
|
|
current_storage = sc_global;//FIXME
|
|
current_func = nullptr;
|
|
}
|
|
;
|
|
|
|
variable_identifier
|
|
: IDENTIFIER
|
|
;
|
|
|
|
primary_exprsssion
|
|
: variable_identifier { $$ = new_symbol_expr ($1); }
|
|
| VALUE
|
|
| '(' expression ')' { $$ = $2; ((expr_t *) $$)->paren = 1; }
|
|
;
|
|
|
|
postfix_expression
|
|
: primary_exprsssion
|
|
| postfix_expression '[' integer_expression ']'
|
|
{
|
|
$$ = array_expr ($1, $3);
|
|
}
|
|
| function_call
|
|
| postfix_expression '.' IDENTIFIER/*FIELD_SELECTION*/
|
|
{
|
|
auto sym = new_symbol_expr ($3);
|
|
$$ = field_expr ($1, sym);
|
|
}
|
|
| postfix_expression INCOP { $$ = incop_expr ($2, $1, 1); }
|
|
;
|
|
|
|
integer_expression
|
|
: expression
|
|
;
|
|
|
|
function_call
|
|
: function_call_or_method
|
|
;
|
|
|
|
function_call_or_method
|
|
: function_call_generic
|
|
;
|
|
|
|
function_call_generic
|
|
: function_call_header_with_parameters ')'
|
|
| function_call_header_no_parameters ')'
|
|
;
|
|
|
|
function_call_header_no_parameters
|
|
: function_call_header VOID
|
|
| function_call_header
|
|
;
|
|
|
|
function_call_header_with_parameters
|
|
: function_call_header assignment_expression
|
|
| function_call_header_with_parameters ',' assignment_expression
|
|
;
|
|
|
|
function_call_header
|
|
: function_identifier '('
|
|
;
|
|
|
|
function_identifier
|
|
: type_specifier { }
|
|
| postfix_expression
|
|
;
|
|
|
|
unary_expression
|
|
: postfix_expression
|
|
| INCOP unary_expression { $$ = incop_expr ($1, $2, 0); }
|
|
| unary_operator unary_expression { $$ = unary_expr ($1, $2); }
|
|
;
|
|
|
|
unary_operator
|
|
: '+' { $$ = '+'; }
|
|
| '-' { $$ = '-'; }
|
|
| '!' { $$ = '!'; }
|
|
| '~' { $$ = '~'; }
|
|
;
|
|
|
|
multiplicative_expression
|
|
: unary_expression
|
|
| multiplicative_expression '*' unary_expression
|
|
{
|
|
$$ = binary_expr ('*', $1, $3);
|
|
}
|
|
| multiplicative_expression '/' unary_expression
|
|
{
|
|
$$ = binary_expr ('/', $1, $3);
|
|
}
|
|
| multiplicative_expression '%' unary_expression
|
|
{
|
|
$$ = binary_expr ('%', $1, $3);
|
|
}
|
|
;
|
|
|
|
additive_expression
|
|
: multiplicative_expression
|
|
| additive_expression '+' unary_expression
|
|
{
|
|
$$ = binary_expr ('+', $1, $3);
|
|
}
|
|
| additive_expression '-' unary_expression
|
|
{
|
|
$$ = binary_expr ('-', $1, $3);
|
|
}
|
|
;
|
|
|
|
shift_expression
|
|
: additive_expression
|
|
| shift_expression SHL additive_expression
|
|
{
|
|
$$ = binary_expr (QC_SHL, $1, $3);
|
|
}
|
|
| shift_expression SHR additive_expression
|
|
{
|
|
$$ = binary_expr (QC_SHR, $1, $3);
|
|
}
|
|
;
|
|
|
|
relational_expression
|
|
: shift_expression
|
|
| relational_expression LT shift_expression
|
|
{
|
|
$$ = binary_expr (QC_LT, $1, $3);
|
|
}
|
|
| relational_expression GT shift_expression
|
|
{
|
|
$$ = binary_expr (QC_GT, $1, $3);
|
|
}
|
|
| relational_expression LE shift_expression
|
|
{
|
|
$$ = binary_expr (QC_LE, $1, $3);
|
|
}
|
|
| relational_expression GE shift_expression
|
|
{
|
|
$$ = binary_expr (QC_GE, $1, $3);
|
|
}
|
|
;
|
|
|
|
equality_expression
|
|
: relational_expression
|
|
| equality_expression EQ relational_expression
|
|
{
|
|
$$ = binary_expr (QC_EQ, $1, $3);
|
|
}
|
|
| relational_expression NE relational_expression
|
|
{
|
|
$$ = binary_expr (QC_NE, $1, $3);
|
|
}
|
|
;
|
|
|
|
and_expression
|
|
: equality_expression
|
|
| and_expression '&' equality_expression
|
|
{
|
|
$$ = binary_expr ('&', $1, $3);
|
|
}
|
|
;
|
|
|
|
exclusive_or_expression
|
|
: and_expression
|
|
| exclusive_or_expression '^' and_expression
|
|
{
|
|
$$ = binary_expr ('^', $1, $3);
|
|
}
|
|
;
|
|
|
|
inclusive_or_expression
|
|
: exclusive_or_expression
|
|
| inclusive_or_expression '|' exclusive_or_expression
|
|
{
|
|
$$ = binary_expr ('|', $1, $3);
|
|
}
|
|
;
|
|
|
|
logical_and_expression
|
|
: inclusive_or_expression
|
|
| logical_and_expression AND inclusive_or_expression
|
|
{
|
|
$$ = bool_expr (QC_AND, nullptr, $1, $3);
|
|
}
|
|
;
|
|
|
|
logical_xor_expression
|
|
: logical_and_expression
|
|
| logical_xor_expression XOR logical_and_expression
|
|
{
|
|
$$ = bool_expr (QC_XOR, nullptr, $1, $3);
|
|
}
|
|
;
|
|
|
|
logical_or_expression
|
|
: logical_xor_expression
|
|
| logical_or_expression OR logical_xor_expression
|
|
{
|
|
$$ = bool_expr (QC_OR, nullptr, $1, $3);
|
|
}
|
|
;
|
|
|
|
conditional_expression
|
|
: logical_or_expression
|
|
| logical_or_expression '?' expression ':' assignment_expression
|
|
{
|
|
$$ = conditional_expr ($1, $3, $5);
|
|
}
|
|
;
|
|
|
|
assignment_expression
|
|
: conditional_expression
|
|
| unary_expression assignment_operator assignment_expression
|
|
{
|
|
if ($2 == '=') {
|
|
$$ = assign_expr ($1, $3);
|
|
} else {
|
|
$$ = asx_expr ($2, $1, $3);
|
|
}
|
|
}
|
|
;
|
|
|
|
assignment_operator
|
|
: '=' { $$ = '='; }
|
|
| ASX
|
|
;
|
|
|
|
expression
|
|
: assignment_expression
|
|
| expression ',' assignment_expression
|
|
;
|
|
|
|
constant_expression
|
|
: conditional_expression
|
|
;
|
|
|
|
declaration
|
|
: function_prototype ';'
|
|
| init_declarator_list ';'
|
|
| PRECISION precision_qualifier type_specifier ';'
|
|
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' ';'
|
|
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' IDENTIFIER ';'
|
|
| type_qualifier IDENTIFIER '{' struct_declaration_list '}' IDENTIFIER array_specifier ';'
|
|
| type_qualifier ';'
|
|
| type_qualifier IDENTIFIER ';'
|
|
| type_qualifier IDENTIFIER identifier_list ';'
|
|
;
|
|
|
|
identifier_list
|
|
: ',' IDENTIFIER
|
|
| identifier_list ',' IDENTIFIER
|
|
;
|
|
|
|
function_prototype
|
|
: function_declarator ')'
|
|
;
|
|
|
|
function_declarator
|
|
: function_header
|
|
| function_header_with_parameters
|
|
;
|
|
|
|
function_header_with_parameters
|
|
: function_header parameter_declaration
|
|
{
|
|
auto spec = $1;
|
|
spec.params = $2;
|
|
$$ = spec;
|
|
}
|
|
| function_header_with_parameters ',' parameter_declaration
|
|
{
|
|
auto spec = $1;
|
|
spec.params = append_params (spec.params, $3);
|
|
$$ = spec;
|
|
}
|
|
;
|
|
|
|
function_header
|
|
: fully_specified_type IDENTIFIER '('
|
|
{
|
|
auto spec = $1;
|
|
if ($2->table) {
|
|
spec.sym = new_symbol ($2->name);
|
|
} else {
|
|
spec.sym = $2;
|
|
}
|
|
$$ = spec;
|
|
}
|
|
;
|
|
|
|
parameter_declarator
|
|
: type_specifier IDENTIFIER
|
|
{
|
|
$$ = new_param (nullptr, $1.type, $2->name);
|
|
}
|
|
| type_specifier IDENTIFIER array_specifier
|
|
{
|
|
$$ = new_param (nullptr, append_type ($1.type, $3), $2->name);
|
|
}
|
|
;
|
|
|
|
parameter_declaration
|
|
: type_qualifier parameter_declarator { $$ = $2; }//XXX
|
|
| parameter_declarator
|
|
| type_qualifier parameter_type_specifier { $$ = $2; }//XXX
|
|
| parameter_type_specifier
|
|
;
|
|
|
|
parameter_type_specifier
|
|
: type_specifier
|
|
{
|
|
$$ = new_param (nullptr, $1.type, nullptr);
|
|
}
|
|
;
|
|
|
|
init_declarator_list
|
|
: single_declaration
|
|
| init_declarator_list ',' IDENTIFIER
|
|
{
|
|
auto symtab = current_symtab;
|
|
auto space = symtab->space;
|
|
auto storage = current_storage;
|
|
initialize_def ($3, nullptr, space, storage, symtab);
|
|
}
|
|
| init_declarator_list ',' IDENTIFIER array_specifier
|
|
| init_declarator_list ',' IDENTIFIER array_specifier '=' initializer
|
|
| init_declarator_list ',' IDENTIFIER '=' initializer
|
|
{
|
|
auto symtab = current_symtab;
|
|
auto space = symtab->space;
|
|
auto storage = current_storage;
|
|
initialize_def ($3, $5, space, storage, symtab);
|
|
}
|
|
;
|
|
|
|
single_declaration
|
|
: fully_specified_type
|
|
| fully_specified_type IDENTIFIER
|
|
| fully_specified_type IDENTIFIER array_specifier
|
|
| fully_specified_type IDENTIFIER array_specifier '=' initializer
|
|
| fully_specified_type IDENTIFIER '=' initializer
|
|
;
|
|
|
|
fully_specified_type
|
|
: type_specifier
|
|
| type_qualifier type_specifier
|
|
;
|
|
|
|
invariant_qualifier
|
|
: INVARIANT
|
|
;
|
|
|
|
interpolation_qualifier
|
|
: SMOOTH
|
|
| FLAT
|
|
| NOPERSPECTIVE
|
|
;
|
|
|
|
layout_qualifier
|
|
: LAYOUT '(' layout_qualifer_id_list ')'
|
|
;
|
|
|
|
layout_qualifer_id_list
|
|
: layout_qualifer_id
|
|
| layout_qualifer_id_list ',' layout_qualifer_id
|
|
;
|
|
|
|
layout_qualifer_id
|
|
: IDENTIFIER
|
|
| IDENTIFIER '=' constant_expression
|
|
| SHARED
|
|
;
|
|
|
|
precise_qualifer
|
|
: PRECISE
|
|
;
|
|
|
|
type_qualifier
|
|
: single_type_qualifier
|
|
| type_qualifier single_type_qualifier
|
|
;
|
|
|
|
single_type_qualifier
|
|
: storage_qualifier
|
|
| layout_qualifier
|
|
| precision_qualifier
|
|
| interpolation_qualifier
|
|
| invariant_qualifier
|
|
| precise_qualifer
|
|
;
|
|
|
|
storage_qualifier
|
|
: CONST
|
|
| IN
|
|
| OUT
|
|
| INOUT
|
|
| CENTROID
|
|
| PATCH
|
|
| SAMPLE
|
|
| UNIFORM
|
|
| BUFFER
|
|
| SHARED
|
|
| COHERENT
|
|
| VOLATILE
|
|
| RESTRICT
|
|
| READONLY
|
|
| WRITEONLY
|
|
;
|
|
|
|
type_specifier
|
|
: type_specifier_nonarray
|
|
| type_specifier_nonarray array_specifier
|
|
;
|
|
|
|
array_specifier
|
|
: array_size { $$ = (type_t *) array_type (nullptr, $1); }
|
|
| array_specifier array_size
|
|
{
|
|
$$ = (type_t *) append_type ($1, array_type (nullptr, $2));
|
|
}
|
|
;
|
|
|
|
array_size
|
|
: '[' ']' { $$ = 0; }
|
|
| '[' conditional_expression ']'
|
|
{
|
|
if (is_int_val ($2) && expr_int ($2) > 0) {
|
|
$$ = expr_int ($2);
|
|
} else if (is_uint_val ($2) && expr_uint ($2) > 0) {
|
|
$$ = expr_uint ($2);
|
|
} else{
|
|
error (0, "invalid array size");
|
|
$$ = 0;
|
|
}
|
|
}
|
|
;
|
|
|
|
type_specifier_nonarray
|
|
: VOID
|
|
| TYPE_SPEC
|
|
| struct_specifier
|
|
| TYPE_NAME
|
|
;
|
|
|
|
precision_qualifier
|
|
: HIGH_PRECISION
|
|
| MEDIUM_PRECISION
|
|
| LOW_PRECISION
|
|
;
|
|
|
|
struct_specifier
|
|
: STRUCT IDENTIFIER '{'
|
|
{
|
|
int op = 's';
|
|
current_symtab = start_struct (&op, $2, current_symtab);
|
|
}
|
|
struct_declaration_list '}'
|
|
{
|
|
auto symtab = current_symtab;
|
|
current_symtab = symtab->parent;
|
|
|
|
auto sym = build_struct ('s', $2, symtab, nullptr, 0);
|
|
if (!sym->table) {
|
|
symtab_addsymbol (current_symtab, sym);
|
|
}
|
|
auto s = $2;
|
|
s->sy_type = sy_type;
|
|
s->type = find_type (alias_type (sym->type, sym->type, s->name));
|
|
symtab_addsymbol (current_symtab, s);
|
|
}
|
|
| STRUCT '{'
|
|
{
|
|
int op = 's';
|
|
current_symtab = start_struct (&op, nullptr, current_symtab);
|
|
}
|
|
struct_declaration_list '}'
|
|
{
|
|
auto symtab = current_symtab;
|
|
current_symtab = symtab->parent;
|
|
|
|
auto sym = build_struct ('s', nullptr, symtab, nullptr, 0);
|
|
if (!sym->table) {
|
|
symtab_addsymbol (current_symtab, sym);
|
|
}
|
|
}
|
|
;
|
|
|
|
struct_declaration_list
|
|
: struct_declaration
|
|
| struct_declaration_list struct_declaration
|
|
;
|
|
|
|
struct_declaration
|
|
: type_specifier struct_declarator_list ';'
|
|
| type_qualifier type_specifier struct_declarator_list ';'
|
|
;
|
|
|
|
struct_declarator_list
|
|
: struct_declarator
|
|
| struct_declarator_list ',' struct_declarator
|
|
;
|
|
|
|
struct_declarator
|
|
: IDENTIFIER
|
|
| IDENTIFIER array_specifier
|
|
;
|
|
|
|
initializer
|
|
: assignment_expression
|
|
| '{' initializer_list '}' { $$ = $2; }
|
|
| '{' initializer_list ',' '}' { $$ = $2; }
|
|
;
|
|
|
|
initializer_list
|
|
: initializer
|
|
{
|
|
$$ = new_compound_init ();
|
|
append_element ($$, new_element ($1, nullptr));
|
|
}
|
|
| initializer_list ',' initializer
|
|
{
|
|
append_element ($$, new_element ($3, nullptr));
|
|
}
|
|
;
|
|
|
|
declaration_statement
|
|
: declaration { $$ = nullptr; }
|
|
;
|
|
|
|
statement
|
|
: compound_statement
|
|
| simple_statement
|
|
;
|
|
|
|
simple_statement
|
|
: declaration_statement
|
|
| expression_statement
|
|
| selection_statement
|
|
| switch_statement
|
|
| case_label
|
|
| iteration_statement
|
|
| jump_statement
|
|
;
|
|
|
|
compound_statement
|
|
: '{' '}' { $$ = nullptr; }
|
|
| '{' statement_list '}' { $$ = $2; }
|
|
;
|
|
|
|
statement_no_new_scope
|
|
: compound_statement_no_new_scope
|
|
| simple_statement
|
|
;
|
|
|
|
compound_statement_no_new_scope
|
|
: '{' '}' { $$ = nullptr; }
|
|
| '{' statement_list '}' { $$ = $2; }
|
|
;
|
|
|
|
statement_list
|
|
: statement
|
|
{
|
|
auto list = new_block_expr (nullptr);
|
|
append_expr (list, $1);
|
|
$$ = list;
|
|
}
|
|
| statement_list statement
|
|
{
|
|
auto list = (expr_t *) $1;
|
|
append_expr (list, $2);
|
|
$$ = list;
|
|
}
|
|
;
|
|
|
|
expression_statement
|
|
: ';' { $$ = nullptr; }
|
|
| expression ';' { $$ = (expr_t *) $expression; }
|
|
;
|
|
|
|
selection_statement
|
|
// : IF '(' expression ')' selection_rest_statement
|
|
: IF '(' expression ')' statement[true] %prec IFX
|
|
{
|
|
$$ = build_if_statement (false, $expression,
|
|
$true, nullptr, nullptr);
|
|
}
|
|
| IF '(' expression ')' statement[true] else statement[false]
|
|
{
|
|
$$ = build_if_statement (false, $expression,
|
|
$true, $else, $false);
|
|
}
|
|
;
|
|
|
|
else
|
|
: ELSE
|
|
{
|
|
// this is only to get the the file and line number info
|
|
$$ = new_nil_expr ();
|
|
}
|
|
;
|
|
|
|
//selection_rest_statement
|
|
// : statement ELSE statement
|
|
// | statement %prec IFX
|
|
// ;
|
|
|
|
condition
|
|
: expression
|
|
| fully_specified_type IDENTIFIER '=' initializer
|
|
{
|
|
auto symtab = current_symtab;
|
|
auto space = symtab->space;
|
|
auto storage = current_storage;
|
|
initialize_def ($2, $initializer, space, storage, symtab);
|
|
}
|
|
;
|
|
|
|
break_label
|
|
: /* empty */
|
|
{
|
|
$$ = break_label;
|
|
break_label = new_label_expr ();
|
|
}
|
|
;
|
|
|
|
continue_label
|
|
: /* empty */
|
|
{
|
|
$$ = continue_label;
|
|
continue_label = new_label_expr ();
|
|
}
|
|
;
|
|
|
|
switch_statement
|
|
: SWITCH break_label '(' expression switch_block')'
|
|
'{' switch_statement_list '}'
|
|
{
|
|
$$ = switch_expr (switch_block, break_label,
|
|
$switch_statement_list);
|
|
switch_block = $switch_block;
|
|
break_label = $break_label;
|
|
}
|
|
;
|
|
|
|
switch_block
|
|
: /* empty */
|
|
{
|
|
$$ = switch_block;
|
|
switch_block = new_switch_block ();
|
|
switch_block->test = $<expr>0;
|
|
}
|
|
;
|
|
|
|
switch_statement_list
|
|
: /* empty */ { $$ = nullptr; }
|
|
| statement_list
|
|
;
|
|
|
|
case_label
|
|
: CASE expression ':' { $$ = case_label_expr (switch_block, $2); }
|
|
| DEFAULT ':' { $$ = case_label_expr (switch_block, nullptr); }
|
|
;
|
|
|
|
iteration_statement
|
|
: WHILE break_label continue_label '(' condition ')' statement_no_new_scope
|
|
{
|
|
$$ = build_while_statement (false, $continue_label,
|
|
$statement_no_new_scope, break_label,
|
|
continue_label);
|
|
break_label = $break_label;
|
|
continue_label = $continue_label;
|
|
}
|
|
| DO break_label continue_label statement WHILE '(' expression ')' ';'
|
|
{
|
|
$$ = build_do_while_statement ($statement, false, $expression,
|
|
break_label, continue_label);
|
|
break_label = $break_label;
|
|
continue_label = $continue_label;
|
|
}
|
|
| FOR break_label continue_label
|
|
// '(' for_init_statement for_rest_statement ')'
|
|
'(' for_init_statement ';' conditionopt ';' expressionopt ')'
|
|
statement_no_new_scope
|
|
{
|
|
if ($for_init_statement) {
|
|
$for_init_statement = build_block_expr ((expr_t *) $for_init_statement,
|
|
false);
|
|
}
|
|
$$ = build_for_statement ($for_init_statement, $conditionopt,
|
|
$expressionopt, $statement_no_new_scope,
|
|
break_label, continue_label);
|
|
break_label = $break_label;
|
|
continue_label = $continue_label;
|
|
}
|
|
;
|
|
|
|
for_init_statement
|
|
: expression_statement { $$ = $1; }
|
|
| declaration_statement { $$ = $1; }
|
|
;
|
|
|
|
conditionopt
|
|
: condition
|
|
| /* emtpy */ { $$ = nullptr; }
|
|
;
|
|
|
|
expressionopt
|
|
: expression
|
|
| /* emtpy */ { $$ = nullptr; }
|
|
;
|
|
/*
|
|
for_rest_statement
|
|
: conditionopt ';'
|
|
| conditionopt ';' expression
|
|
;
|
|
*/
|
|
jump_statement
|
|
: CONTINUE ';'
|
|
{
|
|
$$ = nullptr;
|
|
if (continue_label) {
|
|
$$ = goto_expr (continue_label);
|
|
} else {
|
|
error (nullptr, "continue outside of loop");
|
|
}
|
|
}
|
|
| BREAK ';'
|
|
{
|
|
$$ = nullptr;
|
|
if (break_label) {
|
|
$$ = goto_expr (break_label);
|
|
} else {
|
|
error (nullptr, "continue outside of loop or switch");
|
|
}
|
|
}
|
|
| RETURN ';' { $$ = return_expr (current_func, nullptr); }
|
|
| RETURN expression ';' { $$ = return_expr (current_func, $2); }
|
|
| DISCARD ';' { $$ = nullptr; } //XXX
|
|
;
|
|
|
|
%%
|
|
|
|
|
|
static keyword_t glsl_keywords[] = {
|
|
{"const", GLSL_CONST},
|
|
{"uniform", GLSL_UNIFORM},
|
|
{"buffer", GLSL_BUFFER},
|
|
{"shared", GLSL_SHARED},
|
|
{"attribute", GLSL_RESERVED},
|
|
{"varying", GLSL_RESERVED},
|
|
{"coherent", GLSL_COHERENT},
|
|
{"volatile", GLSL_VOLATILE},
|
|
{"restrict", GLSL_RESTRICT},
|
|
{"readonly", GLSL_READONLY},
|
|
{"writeonly", GLSL_WRITEONLY},
|
|
{"atomic_uint", GLSL_RESERVED},
|
|
{"layout", GLSL_LAYOUT},
|
|
{"centroid", GLSL_CENTROID},
|
|
{"flat", GLSL_FLAT},
|
|
{"smooth", GLSL_SMOOTH},
|
|
{"noperspective", GLSL_NOPERSPECTIVE},
|
|
{"patch", GLSL_PATCH},
|
|
{"sample", GLSL_SAMPLE},
|
|
{"invariant", GLSL_INVARIANT},
|
|
{"precise", GLSL_PRECISE},
|
|
{"break", GLSL_BREAK},
|
|
{"continue", GLSL_CONTINUE},
|
|
{"do", GLSL_DO},
|
|
{"for", GLSL_FOR},
|
|
{"while", GLSL_WHILE},
|
|
{"switch", GLSL_SWITCH},
|
|
{"case", GLSL_CASE},
|
|
{"default", GLSL_DEFAULT},
|
|
{"if", GLSL_IF},
|
|
{"else", GLSL_ELSE},
|
|
{"subroutine", GLSL_RESERVED},
|
|
{"in", GLSL_IN},
|
|
{"out", GLSL_OUT},
|
|
{"inout", GLSL_INOUT},
|
|
{"int", GLSL_TYPE_SPEC, .spec = {.type = &type_int}},
|
|
{"void", GLSL_VOID, .spec = {.type = &type_void}},
|
|
{"bool", GLSL_TYPE_SPEC, .spec = {.type = &type_bool}},
|
|
{"true", 0},
|
|
{"false", 0},
|
|
{"float", GLSL_TYPE_SPEC, .spec = {.type = &type_float}},
|
|
{"double", GLSL_TYPE_SPEC, .spec = {.type = &type_double}},
|
|
{"discard", GLSL_DISCARD},
|
|
{"return", GLSL_RETURN},
|
|
{"vec2", GLSL_TYPE_SPEC, .spec = {.type = &type_vec2}},
|
|
{"vec3", GLSL_TYPE_SPEC, .spec = {.type = &type_vec3}},
|
|
{"vec4", GLSL_TYPE_SPEC, .spec = {.type = &type_vec4}},
|
|
{"ivec2", GLSL_TYPE_SPEC, .spec = {.type = &type_ivec2}},
|
|
{"ivec3", GLSL_TYPE_SPEC, .spec = {.type = &type_ivec3}},
|
|
{"ivec4", GLSL_TYPE_SPEC, .spec = {.type = &type_ivec4}},
|
|
{"bvec2", GLSL_TYPE_SPEC, .spec = {.type = &type_bvec2}},
|
|
{"bvec3", GLSL_TYPE_SPEC, .spec = {.type = &type_bvec3}},
|
|
{"bvec4", GLSL_TYPE_SPEC, .spec = {.type = &type_bvec4}},
|
|
{"uint", GLSL_TYPE_SPEC, .spec = {.type = &type_uint}},
|
|
{"uvec2", GLSL_TYPE_SPEC, .spec = {.type = &type_uivec2}},
|
|
{"uvec3", GLSL_TYPE_SPEC, .spec = {.type = &type_uivec3}},
|
|
{"uvec4", GLSL_TYPE_SPEC, .spec = {.type = &type_uivec4}},
|
|
{"dvec2", GLSL_TYPE_SPEC, .spec = {.type = &type_dvec2}},
|
|
{"dvec3", GLSL_TYPE_SPEC, .spec = {.type = &type_dvec3}},
|
|
{"dvec4", GLSL_TYPE_SPEC, .spec = {.type = &type_dvec4}},
|
|
{"mat2", GLSL_TYPE_SPEC, .spec = {.type = &type_mat2x2}},
|
|
{"mat3", GLSL_TYPE_SPEC, .spec = {.type = &type_mat3x3}},
|
|
{"mat4", GLSL_TYPE_SPEC, .spec = {.type = &type_mat4x4}},
|
|
{"mat2x2", GLSL_TYPE_SPEC, .spec = {.type = &type_mat2x2}},
|
|
{"mat2x3", GLSL_TYPE_SPEC, .spec = {.type = &type_mat2x3}},
|
|
{"mat2x4", GLSL_TYPE_SPEC, .spec = {.type = &type_mat2x4}},
|
|
{"mat3x2", GLSL_TYPE_SPEC, .spec = {.type = &type_mat3x2}},
|
|
{"mat3x3", GLSL_TYPE_SPEC, .spec = {.type = &type_mat3x3}},
|
|
{"mat3x4", GLSL_TYPE_SPEC, .spec = {.type = &type_mat3x4}},
|
|
{"mat4x2", GLSL_TYPE_SPEC, .spec = {.type = &type_mat4x2}},
|
|
{"mat4x3", GLSL_TYPE_SPEC, .spec = {.type = &type_mat4x3}},
|
|
{"mat4x4", GLSL_TYPE_SPEC, .spec = {.type = &type_mat4x4}},
|
|
{"dmat2", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat2x2}},
|
|
{"dmat3", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat3x3}},
|
|
{"dmat4", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat4x4}},
|
|
{"dmat2x2", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat2x2}},
|
|
{"dmat2x3", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat2x3}},
|
|
{"dmat2x4", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat2x4}},
|
|
{"dmat3x2", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat3x2}},
|
|
{"dmat3x3", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat3x3}},
|
|
{"dmat3x4", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat3x4}},
|
|
{"dmat4x2", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat4x2}},
|
|
{"dmat4x3", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat4x3}},
|
|
{"dmat4x4", GLSL_TYPE_SPEC, .spec = {.type = &type_dmat4x4}},
|
|
|
|
{"lowp", GLSL_LOW_PRECISION},
|
|
{"mediump", GLSL_MEDIUM_PRECISION},
|
|
{"highp", GLSL_HIGH_PRECISION},
|
|
{"precision", GLSL_PRECISION},
|
|
{"sampler1D", GLSL_TYPE_SPEC}, // spec init at runtime
|
|
{"sampler1DShadow", GLSL_TYPE_SPEC},
|
|
{"sampler1DArray", GLSL_TYPE_SPEC},
|
|
{"sampler1DArrayShadow", GLSL_TYPE_SPEC},
|
|
{"isampler1D", GLSL_TYPE_SPEC},
|
|
{"isampler1DArray", GLSL_TYPE_SPEC},
|
|
{"usampler1D", GLSL_TYPE_SPEC},
|
|
{"usampler1DArray", GLSL_TYPE_SPEC},
|
|
{"sampler2D", GLSL_TYPE_SPEC},
|
|
{"sampler2DShadow", GLSL_TYPE_SPEC},
|
|
{"sampler2DArray", GLSL_TYPE_SPEC},
|
|
{"sampler2DArrayShadow", GLSL_TYPE_SPEC},
|
|
{"isampler2D", GLSL_TYPE_SPEC},
|
|
{"isampler2DArray", GLSL_TYPE_SPEC},
|
|
{"usampler2D", GLSL_TYPE_SPEC},
|
|
{"usampler2DArray", GLSL_TYPE_SPEC},
|
|
{"sampler2DRect", GLSL_TYPE_SPEC},
|
|
{"sampler2DRectShadow", GLSL_TYPE_SPEC},
|
|
{"isampler2DRect", GLSL_TYPE_SPEC},
|
|
{"usampler2DRect", GLSL_TYPE_SPEC},
|
|
{"sampler2DMS", GLSL_TYPE_SPEC},
|
|
{"isampler2DMS", GLSL_TYPE_SPEC},
|
|
{"usampler2DMS", GLSL_TYPE_SPEC},
|
|
{"sampler2DMSArray", GLSL_TYPE_SPEC},
|
|
{"isampler2DMSArray", GLSL_TYPE_SPEC},
|
|
{"usampler2DMSArray", GLSL_TYPE_SPEC},
|
|
{"sampler3D", GLSL_TYPE_SPEC},
|
|
{"isampler3D", GLSL_TYPE_SPEC},
|
|
{"usampler3D", GLSL_TYPE_SPEC},
|
|
{"samplerCube", GLSL_TYPE_SPEC},
|
|
{"samplerCubeShadow", GLSL_TYPE_SPEC},
|
|
{"isamplerCube", GLSL_TYPE_SPEC},
|
|
{"usamplerCube", GLSL_TYPE_SPEC},
|
|
{"samplerCubeArray", GLSL_TYPE_SPEC},
|
|
{"samplerCubeArrayShadow", GLSL_TYPE_SPEC},
|
|
{"isamplerCubeArray", GLSL_TYPE_SPEC},
|
|
{"usamplerCubeArray", GLSL_TYPE_SPEC},
|
|
{"samplerBuffer", GLSL_TYPE_SPEC},
|
|
{"isamplerBuffer", GLSL_TYPE_SPEC},
|
|
{"usamplerBuffer", GLSL_TYPE_SPEC},
|
|
{"image1D", GLSL_TYPE_SPEC},
|
|
{"iimage1D", GLSL_TYPE_SPEC},
|
|
{"uimage1D", GLSL_TYPE_SPEC},
|
|
{"image1DArray", GLSL_TYPE_SPEC},
|
|
{"iimage1DArray", GLSL_TYPE_SPEC},
|
|
{"uimage1DArray", GLSL_TYPE_SPEC},
|
|
{"image2D", GLSL_TYPE_SPEC},
|
|
{"iimage2D", GLSL_TYPE_SPEC},
|
|
{"uimage2D", GLSL_TYPE_SPEC},
|
|
{"image2DArray", GLSL_TYPE_SPEC},
|
|
{"iimage2DArray", GLSL_TYPE_SPEC},
|
|
{"uimage2DArray", GLSL_TYPE_SPEC},
|
|
{"image2DRect", GLSL_TYPE_SPEC},
|
|
{"iimage2DRect", GLSL_TYPE_SPEC},
|
|
{"uimage2DRect", GLSL_TYPE_SPEC},
|
|
{"image2DMS", GLSL_TYPE_SPEC},
|
|
{"iimage2DMS", GLSL_TYPE_SPEC},
|
|
{"uimage2DMS", GLSL_TYPE_SPEC},
|
|
{"image2DMSArray", GLSL_TYPE_SPEC},
|
|
{"iimage2DMSArray", GLSL_TYPE_SPEC},
|
|
{"uimage2DMSArray", GLSL_TYPE_SPEC},
|
|
{"image3D", GLSL_TYPE_SPEC},
|
|
{"iimage3D", GLSL_TYPE_SPEC},
|
|
{"uimage3D", GLSL_TYPE_SPEC},
|
|
{"imageCube", GLSL_TYPE_SPEC},
|
|
{"iimageCube", GLSL_TYPE_SPEC},
|
|
{"uimageCube", GLSL_TYPE_SPEC},
|
|
{"imageCubeArray", GLSL_TYPE_SPEC},
|
|
{"iimageCubeArray", GLSL_TYPE_SPEC},
|
|
{"uimageCubeArray", GLSL_TYPE_SPEC},
|
|
{"imageBuffer", GLSL_TYPE_SPEC},
|
|
{"iimageBuffer", GLSL_TYPE_SPEC},
|
|
{"uimageBuffer", GLSL_TYPE_SPEC},
|
|
|
|
{"struct", GLSL_STRUCT},
|
|
|
|
//vulkan
|
|
{"texture1D", GLSL_TYPE_SPEC}, // spec init at runtime
|
|
{"texture1DArray", GLSL_TYPE_SPEC},
|
|
{"itexture1D", GLSL_TYPE_SPEC},
|
|
{"itexture1DArray", GLSL_TYPE_SPEC},
|
|
{"utexture1D", GLSL_TYPE_SPEC},
|
|
{"utexture1DArray", GLSL_TYPE_SPEC},
|
|
{"texture2D", GLSL_TYPE_SPEC},
|
|
{"texture2DArray", GLSL_TYPE_SPEC},
|
|
{"itexture2D", GLSL_TYPE_SPEC},
|
|
{"itexture2DArray", GLSL_TYPE_SPEC},
|
|
{"utexture2D", GLSL_TYPE_SPEC},
|
|
{"utexture2DArray", GLSL_TYPE_SPEC},
|
|
{"texture2DRect", GLSL_TYPE_SPEC},
|
|
{"itexture2DRect", GLSL_TYPE_SPEC},
|
|
{"utexture2DRect", GLSL_TYPE_SPEC},
|
|
{"texture2DMS", GLSL_TYPE_SPEC},
|
|
{"itexture2DMS", GLSL_TYPE_SPEC},
|
|
{"utexture2DMS", GLSL_TYPE_SPEC},
|
|
{"texture2DMSArray", GLSL_TYPE_SPEC},
|
|
{"itexture2DMSArray", GLSL_TYPE_SPEC},
|
|
{"utexture2DMSArray", GLSL_TYPE_SPEC},
|
|
{"texture3D", GLSL_TYPE_SPEC},
|
|
{"itexture3D", GLSL_TYPE_SPEC},
|
|
{"utexture3D", GLSL_TYPE_SPEC},
|
|
{"textureCube", GLSL_TYPE_SPEC},
|
|
{"itextureCube", GLSL_TYPE_SPEC},
|
|
{"utextureCube", GLSL_TYPE_SPEC},
|
|
{"textureCubeArray", GLSL_TYPE_SPEC},
|
|
{"itextureCubeArray", GLSL_TYPE_SPEC},
|
|
{"utextureCubeArray", GLSL_TYPE_SPEC},
|
|
{"textureBuffer", GLSL_TYPE_SPEC},
|
|
{"itextureBuffer", GLSL_TYPE_SPEC},
|
|
{"utextureBuffer", GLSL_TYPE_SPEC},
|
|
{"sampler", GLSL_TYPE_SPEC},
|
|
{"samplerShadow", GLSL_TYPE_SPEC},
|
|
{"subpassInput", GLSL_TYPE_SPEC},
|
|
{"isubpassInput", GLSL_TYPE_SPEC},
|
|
{"usubpassInput", GLSL_TYPE_SPEC},
|
|
{"subpassInputMS", GLSL_TYPE_SPEC},
|
|
{"isubpassInputMS", GLSL_TYPE_SPEC},
|
|
{"usubpassInputMS", GLSL_TYPE_SPEC},
|
|
|
|
//reserved
|
|
{"common", GLSL_RESERVED},
|
|
{"partition", GLSL_RESERVED},
|
|
{"active", GLSL_RESERVED},
|
|
{"asm", GLSL_RESERVED},
|
|
{"class", GLSL_RESERVED},
|
|
{"union", GLSL_RESERVED},
|
|
{"enum", GLSL_RESERVED},
|
|
{"typedef", GLSL_RESERVED},
|
|
{"template", GLSL_RESERVED},
|
|
{"this", GLSL_RESERVED},
|
|
{"resource", GLSL_RESERVED},
|
|
{"goto", GLSL_RESERVED},
|
|
{"inline", GLSL_RESERVED},
|
|
{"noinline", GLSL_RESERVED},
|
|
{"public", GLSL_RESERVED},
|
|
{"static", GLSL_RESERVED},
|
|
{"extern", GLSL_RESERVED},
|
|
{"external", GLSL_RESERVED},
|
|
{"interface", GLSL_RESERVED},
|
|
{"long", GLSL_RESERVED},
|
|
{"short", GLSL_RESERVED},
|
|
{"half", GLSL_RESERVED},
|
|
{"fixed", GLSL_RESERVED},
|
|
{"unsigned", GLSL_RESERVED},
|
|
{"superp", GLSL_RESERVED},
|
|
{"input", GLSL_RESERVED},
|
|
{"output", GLSL_RESERVED},
|
|
{"hvec2", GLSL_RESERVED},
|
|
{"hvec3", GLSL_RESERVED},
|
|
{"hvec4", GLSL_RESERVED},
|
|
{"fvec2", GLSL_RESERVED},
|
|
{"fvec3", GLSL_RESERVED},
|
|
{"fvec4", GLSL_RESERVED},
|
|
{"filter", GLSL_RESERVED},
|
|
{"sizeof", GLSL_RESERVED},
|
|
{"cast", GLSL_RESERVED},
|
|
{"namespace", GLSL_RESERVED},
|
|
{"using", GLSL_RESERVED},
|
|
{"sampler3DRect", GLSL_RESERVED},
|
|
};
|
|
|
|
// preprocessor directives in ruamoko and quakec
|
|
static directive_t glsl_directives[] = {
|
|
{"include", PRE_INCLUDE},
|
|
{"define", PRE_DEFINE},
|
|
{"undef", PRE_UNDEF},
|
|
{"error", PRE_ERROR},
|
|
{"warning", PRE_WARNING},
|
|
{"notice", PRE_NOTICE},
|
|
{"pragma", PRE_PRAGMA},
|
|
{"line", PRE_LINE},
|
|
|
|
{"extension", PRE_EXTENSION},
|
|
{"version", PRE_VERSION},
|
|
};
|
|
|
|
static directive_t *
|
|
glsl_directive (const char *token)
|
|
{
|
|
static hashtab_t *directive_tab;
|
|
|
|
if (!directive_tab) {
|
|
directive_tab = Hash_NewTable (253, rua_directive_get_key, 0, 0, 0);
|
|
for (size_t i = 0; i < ARRCOUNT(glsl_directives); i++) {
|
|
Hash_Add (directive_tab, &glsl_directives[i]);
|
|
}
|
|
}
|
|
directive_t *directive = Hash_Find (directive_tab, token);
|
|
return directive;
|
|
}
|
|
|
|
static int
|
|
glsl_process_keyword (rua_val_t *lval, keyword_t *keyword, const char *token)
|
|
{
|
|
if (keyword->value == GLSL_STRUCT) {
|
|
lval->op = token[0];
|
|
} else if (keyword->value == GLSL_TYPE_SPEC && !keyword->spec.type) {
|
|
auto sym = new_symbol (token);
|
|
sym = find_handle (sym, &type_int);
|
|
keyword->spec.type = sym->type;
|
|
lval->spec = keyword->spec;
|
|
} else {
|
|
lval->spec = keyword->spec;
|
|
}
|
|
return keyword->value;
|
|
}
|
|
|
|
static int
|
|
glsl_keyword_or_id (rua_val_t *lval, const char *token)
|
|
{
|
|
static hashtab_t *glsl_keyword_tab;
|
|
|
|
keyword_t *keyword = 0;
|
|
symbol_t *sym;
|
|
|
|
if (!glsl_keyword_tab) {
|
|
size_t i;
|
|
|
|
glsl_keyword_tab = Hash_NewTable (253, rua_keyword_get_key, 0, 0, 0);
|
|
|
|
for (i = 0; i < ARRCOUNT(glsl_keywords); i++)
|
|
Hash_Add (glsl_keyword_tab, &glsl_keywords[i]);
|
|
}
|
|
keyword = Hash_Find (glsl_keyword_tab, token);
|
|
if (keyword && keyword->value)
|
|
return glsl_process_keyword (lval, keyword, token);
|
|
if (token[0] == '@') {
|
|
return '@';
|
|
}
|
|
sym = symtab_lookup (current_symtab, token);
|
|
if (!sym)
|
|
sym = new_symbol (token);
|
|
lval->symbol = sym;
|
|
if (sym->sy_type == sy_type) {
|
|
lval->spec = (specifier_t) {
|
|
.type = sym->type,
|
|
.sym = sym,
|
|
};
|
|
return GLSL_TYPE_NAME;
|
|
}
|
|
return GLSL_IDENTIFIER;
|
|
}
|
|
|
|
int
|
|
glsl_yyparse (FILE *in)
|
|
{
|
|
rua_parser_t parser = {
|
|
.parse = glsl_yypush_parse,
|
|
.state = glsl_yypstate_new (),
|
|
.directive = glsl_directive,
|
|
.keyword_or_id = glsl_keyword_or_id,
|
|
};
|
|
int ret = rua_parse (in, &parser);
|
|
glsl_yypstate_delete (parser.state);
|
|
return ret;
|
|
}
|