2010-11-10 12:32:34 +01:00
|
|
|
|
2010-11-10 15:44:59 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** 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.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
2010-11-10 12:32:34 +01:00
|
|
|
#include "glslparser.h"
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
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<int> parenStack;
|
|
|
|
|
std::stack<int> bracketStack;
|
|
|
|
|
std::stack<int> 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;
|
|
|
|
|
}
|