forked from qt-creator/qt-creator
142 lines
3.6 KiB
C++
142 lines
3.6 KiB
C++
|
|
|
||
|
|
#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;
|
||
|
|
}
|