/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "glslparser.h" #include #include using namespace GLSL; namespace GLSL { void dumpAST(AST *); void deleteAST(AST *ast); } Parser::Parser(const char *source, unsigned size, int variant) : _tos(-1), _index(0) { _tokens.reserve(1024); _stateStack.resize(128); _locationStack.resize(128); _astStack.resize(128); _tokens.push_back(Token()); // invalid token std::stack parenStack; std::stack bracketStack; std::stack braceStack; Lexer lexer(source, size); lexer.setVariant(variant); Token tk; do { lexer.yylex(&tk); switch (tk.kind) { case T_LEFT_PAREN: parenStack.push(_tokens.size()); break; case T_LEFT_BRACKET: bracketStack.push(_tokens.size()); break; case T_LEFT_BRACE: braceStack.push(_tokens.size()); break; case T_RIGHT_PAREN: if (! parenStack.empty()) { _tokens[parenStack.top()].matchingBrace = _tokens.size(); parenStack.pop(); } break; case T_RIGHT_BRACKET: if (! bracketStack.empty()) { _tokens[bracketStack.top()].matchingBrace = _tokens.size(); bracketStack.pop(); } break; case T_RIGHT_BRACE: if (! braceStack.empty()) { _tokens[braceStack.top()].matchingBrace = _tokens.size(); braceStack.pop(); } break; default: break; } _tokens.push_back(tk); } while (tk.isNot(EOF_SYMBOL)); _index = 1; } Parser::~Parser() { } void Parser::dump(AST *ast) { dumpAST(ast); } bool Parser::parse() { int action = 0; int yytoken = -1; int yyloc = -1; Operand *opd = 0; _tos = -1; do { if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { yyloc = consumeToken(); yytoken = tokenKind(yyloc); if (yytoken == T_IDENTIFIER && t_action(action, T_TYPE_NAME) != 0) { const Token &la = tokenAt(_index); if (la.is(T_IDENTIFIER)) { yytoken = T_TYPE_NAME; } else if (la.is(T_LEFT_BRACKET) && la.matchingBrace != 0 && tokenAt(la.matchingBrace + 1).is(T_IDENTIFIER)) { yytoken = T_TYPE_NAME; } } opd = new Operand(yyloc); } if (unsigned(++_tos) == _stateStack.size()) { _stateStack.resize(_tos * 2); _locationStack.resize(_tos * 2); _astStack.resize(_tos * 2); } _stateStack[_tos] = action; action = t_action(action, yytoken); if (action > 0) { if (action == ACCEPT_STATE) { --_tos; dump(_astStack[0]); deleteAST(_astStack[0]); return true; } _astStack[_tos] = opd; _locationStack[_tos] = yyloc; yytoken = -1; } else if (action < 0) { const int ruleno = -action - 1; const int N = rhs[ruleno]; _tos -= N; if (N == 0) _astStack[_tos] = 0; else _astStack[_tos] = new Operator(ruleno, &_astStack[_tos], &_astStack[_tos + N]); action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT); } } while (action); fprintf(stderr, "unexpected token `%s' at line %d\n", yytoken != -1 ? spell[yytoken] : "", _tokens[yyloc].line + 1); return false; }