---------------------------------------------------------------------------- -- -- Copyright (C) 2016 The Qt Company Ltd. -- Contact: https://www.qt.io/licensing/ -- -- This file is part of the QtCore module of the Qt Toolkit. -- -- $QT_BEGIN_LICENSE:GPL-EXCEPT$ -- Commercial License Usage -- Licensees holding valid commercial Qt licenses may use this file in -- accordance with the commercial license agreement provided with the -- Software or, alternatively, in accordance with the terms contained in -- a written agreement between you and The Qt Company. For licensing terms -- and conditions see https://www.qt.io/terms-conditions. For further -- information use the contact form at https://www.qt.io/contact-us. -- -- GNU General Public License Usage -- Alternatively, this file may be used under the terms of the GNU -- General Public License version 3 as published by the Free Software -- Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -- included in the packaging of this file. Please review the following -- information to ensure the GNU General Public License requirements will -- be met: https://www.gnu.org/licenses/gpl-3.0.html. -- -- $QT_END_LICENSE$ -- ---------------------------------------------------------------------------- %parser GLSLParserTable %merged_output glsl.cpp %token ADD_ASSIGN %token AMPERSAND %token AND_ASSIGN %token AND_OP %token ATTRIBUTE %token BANG %token BOOL %token BOOLCONSTANT %token BREAK %token BVEC2 %token BVEC3 %token BVEC4 %token CARET %token COLON %token COMMA %token CONST %token CONTINUE %token DASH %token DEC_OP %token DISCARD %token DIV_ASSIGN %token DO %token DOT %token ELSE %token EQUAL %token EQ_OP %token FLOAT %token FLOATCONSTANT %token FOR %token GE_OP %token IDENTIFIER %token IF %token IN %token INC_OP %token INOUT %token INT %token INTCONSTANT %token IVEC2 %token IVEC3 %token IVEC4 %token LEFT_ANGLE %token LEFT_ASSIGN %token LEFT_BRACE %token LEFT_BRACKET %token LEFT_OP %token LEFT_PAREN %token LE_OP %token MAT2 %token MAT3 %token MAT4 %token MOD_ASSIGN %token MUL_ASSIGN %token NE_OP %token OR_ASSIGN %token OR_OP %token OUT %token PERCENT %token PLUS %token QUESTION %token RETURN %token RIGHT_ANGLE %token RIGHT_ASSIGN %token RIGHT_BRACE %token RIGHT_BRACKET %token RIGHT_OP %token RIGHT_PAREN %token SAMPLER1D %token SAMPLER1DSHADOW %token SAMPLER2D %token SAMPLER2DSHADOW %token SAMPLER3D %token SAMPLERCUBE %token SEMICOLON %token SLASH %token STAR %token STRUCT %token SUB_ASSIGN %token TILDE %token TYPE_NAME %token UNIFORM %token VARYING %token VEC2 %token VEC3 %token VEC4 %token VERTICAL_BAR %token VOID %token WHILE %token XOR_ASSIGN %token XOR_OP %token ERROR %token HIGH_PRECISION %token MEDIUM_PRECISION %token LOW_PRECISION %start translation_unit /: #include class GLSLParser: protected $table { public: union Value { int i; unsigned u; unsigned long ul; unsigned long long ull; long l; double d; float f; const QString *s; // ### more... }; public: GLSLParser(); ~GLSLParser(); bool parse(); protected: inline void reallocateStack(); inline Value &sym(int index) { return sym_stack [tos + index - 1]; } int nextToken(); bool isTypename(const QString *s) const { return types.contains(s); } inline const QString *intern(const QString &s) { return &*string_repository.insert(s); } protected: int tos; int stack_size; Value *sym_stack; int *state_stack; Value yylval; QSet string_repository; QSet types; struct /*Context*/ { int line; const QString *function_name; QString fileName; void init() { line = 1; function_name = 0; fileName.clear(); } } context; }; inline void GLSLParser::reallocateStack() { if (! stack_size) stack_size = 128; else stack_size <<= 1; sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); } :/ /. GLSLParser::GLSLParser(): tos(0), stack_size(0), sym_stack(0), state_stack(0) { } GLSLParser::~GLSLParser() { if (stack_size) { free(sym_stack); free(state_stack); } } bool GLSLParser::parse() { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); context.init(); tos = 0; state_stack[++tos] = INITIAL_STATE; while (true) { if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]]) yytoken = nextToken(); int act = t_action (state_stack [tos], yytoken); if (act == ACCEPT_STATE) { return true; } else if (act > 0) { if (++tos == stack_size) reallocateStack(); sym_stack [tos] = yylval; state_stack [tos] = act; yytoken = -1; } else if (act < 0) { int r = - act - 1; int ridx = rule_index [r]; printf ("--* reduce using rule %d %s ::=", r + 1, spell[rule_info [ridx]]); ++ridx; for (int i = ridx; i < ridx + rhs [r]; ++i) { int symbol = rule_info [i]; if (const char *name = spell [symbol]) printf (" %s", name); else printf (" #%d", symbol); } printf ("\n"); tos -= rhs [r]; act = state_stack [tos++]; switch (r) { ./ translation_unit ::= external_declaration ; translation_unit ::= translation_unit external_declaration ; variable_identifier ::= IDENTIFIER ; primary_expression ::= variable_identifier ; primary_expression ::= INTCONSTANT ; primary_expression ::= FLOATCONSTANT ; primary_expression ::= BOOLCONSTANT ; primary_expression ::= LEFT_PAREN expression RIGHT_PAREN ; postfix_expression ::= primary_expression ; postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ; postfix_expression ::= function_call ; postfix_expression ::= postfix_expression DOT IDENTIFIER ; postfix_expression ::= postfix_expression DOT TYPE_NAME ; postfix_expression ::= postfix_expression INC_OP ; postfix_expression ::= postfix_expression DEC_OP ; integer_expression ::= expression ; function_call ::= function_call_generic ; function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ; function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ; function_call_header_no_parameters ::= function_call_header VOID ; function_call_header_no_parameters ::= function_call_header ; function_call_header_with_parameters ::= function_call_header assignment_expression ; function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ; function_call_header ::= function_identifier LEFT_PAREN ; function_identifier ::= constructor_identifier ; function_identifier ::= IDENTIFIER ; constructor_identifier ::= FLOAT ; constructor_identifier ::= INT ; constructor_identifier ::= BOOL ; constructor_identifier ::= VEC2 ; constructor_identifier ::= VEC3 ; constructor_identifier ::= VEC4 ; constructor_identifier ::= BVEC2 ; constructor_identifier ::= BVEC3 ; constructor_identifier ::= BVEC4 ; constructor_identifier ::= IVEC2 ; constructor_identifier ::= IVEC3 ; constructor_identifier ::= IVEC4 ; constructor_identifier ::= MAT2 ; constructor_identifier ::= MAT3 ; constructor_identifier ::= MAT4 ; constructor_identifier ::= TYPE_NAME ; unary_expression ::= postfix_expression ; unary_expression ::= INC_OP unary_expression ; unary_expression ::= DEC_OP unary_expression ; unary_expression ::= unary_operator unary_expression ; -- Grammar Note: No traditional style type casts. unary_operator ::= PLUS ; unary_operator ::= DASH ; unary_operator ::= BANG ; unary_operator ::= TILDE ; -- reserved -- Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression ::= unary_expression ; multiplicative_expression ::= multiplicative_expression STAR unary_expression ; multiplicative_expression ::= multiplicative_expression SLASH unary_expression ; multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ; -- reserved additive_expression ::= multiplicative_expression ; additive_expression ::= additive_expression PLUS multiplicative_expression ; additive_expression ::= additive_expression DASH multiplicative_expression ; shift_expression ::= additive_expression ; shift_expression ::= shift_expression LEFT_OP additive_expression ; -- reserved shift_expression ::= shift_expression RIGHT_OP additive_expression ; -- reserved relational_expression ::= shift_expression ; relational_expression ::= relational_expression LEFT_ANGLE shift_expression ; relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ; relational_expression ::= relational_expression LE_OP shift_expression ; relational_expression ::= relational_expression GE_OP shift_expression ; equality_expression ::= relational_expression ; equality_expression ::= equality_expression EQ_OP relational_expression ; equality_expression ::= equality_expression NE_OP relational_expression ; and_expression ::= equality_expression ; and_expression ::= and_expression AMPERSAND equality_expression ; -- reserved exclusive_or_expression ::= and_expression ; exclusive_or_expression ::= exclusive_or_expression CARET and_expression ; -- reserved inclusive_or_expression ::= exclusive_or_expression ; inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ; -- reserved logical_and_expression ::= inclusive_or_expression ; logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ; logical_xor_expression ::= logical_and_expression ; logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ; logical_or_expression ::= logical_xor_expression ; logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ; conditional_expression ::= logical_or_expression ; conditional_expression ::= logical_or_expression QUESTION expression COLON conditional_expression ; assignment_expression ::= conditional_expression ; assignment_expression ::= unary_expression assignment_operator assignment_expression ; assignment_operator ::= EQUAL ; assignment_operator ::= MUL_ASSIGN ; assignment_operator ::= DIV_ASSIGN ; assignment_operator ::= MOD_ASSIGN ; -- reserved assignment_operator ::= ADD_ASSIGN ; assignment_operator ::= SUB_ASSIGN ; assignment_operator ::= LEFT_ASSIGN ; -- reserved assignment_operator ::= RIGHT_ASSIGN ; -- reserved assignment_operator ::= AND_ASSIGN ; -- reserved assignment_operator ::= XOR_ASSIGN ; -- reserved assignment_operator ::= OR_ASSIGN ; -- reserved expression ::= assignment_expression ; expression ::= expression COMMA assignment_expression ; constant_expression ::= conditional_expression ; declaration ::= function_prototype SEMICOLON ; declaration ::= init_declarator_list SEMICOLON ; function_prototype ::= function_declarator RIGHT_PAREN ; function_declarator ::= function_header ; function_declarator ::= function_header_with_parameters ; function_header_with_parameters ::= function_header parameter_declaration ; function_header_with_parameters ::= function_header_with_parameters COMMA parameter_declaration ; function_header ::= fully_specified_type IDENTIFIER LEFT_PAREN ; /. case $rule_number: { context.function_name = sym(2).s; } break; ./ parameter_declarator ::= type_specifier IDENTIFIER ; parameter_declarator ::= type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; parameter_declaration ::= type_qualifier parameter_qualifier parameter_declarator ; parameter_declaration ::= parameter_qualifier parameter_declarator ; parameter_declaration ::= type_qualifier parameter_qualifier parameter_type_specifier ; parameter_declaration ::= parameter_qualifier parameter_type_specifier ; parameter_qualifier ::= ; parameter_qualifier ::= IN ; parameter_qualifier ::= OUT ; parameter_qualifier ::= INOUT ; parameter_type_specifier ::= type_specifier ; parameter_type_specifier ::= type_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET ; init_declarator_list ::= single_declaration ; init_declarator_list ::= init_declarator_list COMMA IDENTIFIER ; init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ; init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression ; init_declarator_list ::= RIGHT_BRACKET ; init_declarator_list ::= init_declarator_list COMMA IDENTIFIER EQUAL initializer ; single_declaration ::= fully_specified_type ; single_declaration ::= fully_specified_type IDENTIFIER ; single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ; single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; single_declaration ::= fully_specified_type IDENTIFIER EQUAL initializer ; -- Grammar Note: No 'enum', or 'typedef'. --fully_specified_type ::= type_specifier ; --fully_specified_type ::= type_qualifier type_specifier ; fully_specified_type ::= type_specifier ; fully_specified_type ::= type_qualifier ; fully_specified_type ::= fully_specified_type type_specifier ; fully_specified_type ::= fully_specified_type type_qualifier ; type_qualifier ::= CONST ; type_qualifier ::= ATTRIBUTE ; -- Vertex only. type_qualifier ::= VARYING ; type_qualifier ::= UNIFORM ; type_specifier ::= type_specifier_no_prec ; type_specifier ::= precision_qualifier type_specifier_no_prec ; type_specifier_no_prec ::= VOID ; type_specifier_no_prec ::= FLOAT ; type_specifier_no_prec ::= INT ; type_specifier_no_prec ::= BOOL ; type_specifier_no_prec ::= VEC2 ; type_specifier_no_prec ::= VEC3 ; type_specifier_no_prec ::= VEC4 ; type_specifier_no_prec ::= BVEC2 ; type_specifier_no_prec ::= BVEC3 ; type_specifier_no_prec ::= BVEC4 ; type_specifier_no_prec ::= IVEC2 ; type_specifier_no_prec ::= IVEC3 ; type_specifier_no_prec ::= IVEC4 ; type_specifier_no_prec ::= MAT2 ; type_specifier_no_prec ::= MAT3 ; type_specifier_no_prec ::= MAT4 ; type_specifier_no_prec ::= SAMPLER1D ; type_specifier_no_prec ::= SAMPLER2D ; type_specifier_no_prec ::= SAMPLER3D ; type_specifier_no_prec ::= SAMPLERCUBE ; type_specifier_no_prec ::= SAMPLER1DSHADOW ; type_specifier_no_prec ::= SAMPLER2DSHADOW ; type_specifier_no_prec ::= struct_specifier ; type_specifier_no_prec ::= TYPE_NAME ; precision_qualifier ::= HIGH_PRECISION ; precision_qualifier ::= MEDIUM_PRECISION ; precision_qualifier ::= LOW_PRECISION ; struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ; /. case $rule_number: { types.insert(sym(2).s); } break; ./ struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ; struct_declaration_list ::= struct_declaration ; struct_declaration_list ::= struct_declaration_list struct_declaration ; struct_declaration ::= type_specifier struct_declarator_list SEMICOLON ; struct_declarator_list ::= struct_declarator ; struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ; struct_declarator ::= IDENTIFIER ; struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; initializer ::= assignment_expression ; declaration_statement ::= declaration ; statement ::= compound_statement ; statement ::= simple_statement ; -- Grammar Note: No labeled statements; 'goto' is not supported. simple_statement ::= declaration_statement ; simple_statement ::= expression_statement ; simple_statement ::= selection_statement ; simple_statement ::= iteration_statement ; simple_statement ::= jump_statement ; compound_statement ::= LEFT_BRACE RIGHT_BRACE ; compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ; statement_no_new_scope ::= compound_statement_no_new_scope ; statement_no_new_scope ::= simple_statement ; compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ; compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ; statement_list ::= statement ; statement_list ::= statement_list statement ; expression_statement ::= SEMICOLON ; expression_statement ::= expression SEMICOLON ; selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement ; selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN statement ; -- Grammar Note: No 'switch'. Switch statements not supported. condition ::= expression ; condition ::= fully_specified_type IDENTIFIER EQUAL initializer ; iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ; iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ; iteration_statement ::= FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope ; for_init_statement ::= expression_statement ; for_init_statement ::= declaration_statement ; conditionopt ::= ; conditionopt ::= condition ; for_rest_statement ::= conditionopt SEMICOLON ; for_rest_statement ::= conditionopt SEMICOLON expression ; jump_statement ::= CONTINUE SEMICOLON ; jump_statement ::= BREAK SEMICOLON ; jump_statement ::= RETURN SEMICOLON ; jump_statement ::= RETURN expression SEMICOLON ; jump_statement ::= DISCARD SEMICOLON ; -- Fragment shader only. -- Grammar Note: No 'goto'. Gotos are not supported. external_declaration ::= function_definition ; external_declaration ::= declaration ; function_definition ::= function_prototype compound_statement_no_new_scope ; /. case $rule_number: { // $rule_name qDebug() << "--> function" << *context.function_name; } break; ./ /. } // switch state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT); } else { // ### ERROR RECOVERY HERE break; } } fprintf (stderr, "%s:%d: Syntax Error\n", qPrintable(context.fileName), context.line); return false; } #include "glsl-lex.incl" ///////////////////////////// // entry point ///////////////////////////// int main() { #if 0 // dump the GLSL grammar for (int r = 0; r < GLSLParserTable::RULE_COUNT; ++r) { int ridx = GLSLParserTable::rule_index [r]; int rhs = GLSLParserTable::rhs [r]; printf ("%3d) %s ::=", r + 1, GLSLParserTable::spell[GLSLParserTable::rule_info [ridx]]); ++ridx; for (int i = ridx; i < ridx + rhs; ++i) { int symbol = GLSLParserTable::rule_info [i]; if (const char *name = GLSLParserTable::spell [symbol]) printf (" %s", name); else printf (" #%d", symbol); } printf ("\n"); } #endif GLSLParser parser; if (parser.parse()) qDebug() << "OK"; else qDebug() << "KO"; } ./