summaryrefslogtreecommitdiffstats
path: root/util/qlalr/examples
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:18:55 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:18:55 (GMT)
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /util/qlalr/examples
downloadQt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2
Long live Qt 4.5!
Diffstat (limited to 'util/qlalr/examples')
-rw-r--r--util/qlalr/examples/dummy-xml/dummy-xml.pro2
-rw-r--r--util/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp83
-rw-r--r--util/qlalr/examples/dummy-xml/xml.g202
-rw-r--r--util/qlalr/examples/glsl/build.sh7
-rwxr-xr-xutil/qlalr/examples/glsl/glsl4
-rw-r--r--util/qlalr/examples/glsl/glsl-lex.l201
-rw-r--r--util/qlalr/examples/glsl/glsl.g621
-rw-r--r--util/qlalr/examples/glsl/glsl.pro4
-rw-r--r--util/qlalr/examples/lambda/COMPILE3
-rw-r--r--util/qlalr/examples/lambda/lambda.g41
-rw-r--r--util/qlalr/examples/lambda/lambda.pro3
-rw-r--r--util/qlalr/examples/lambda/main.cpp160
-rw-r--r--util/qlalr/examples/qparser/COMPILE3
-rw-r--r--util/qlalr/examples/qparser/calc.g93
-rw-r--r--util/qlalr/examples/qparser/calc.l20
-rw-r--r--util/qlalr/examples/qparser/qparser.cpp3
-rw-r--r--util/qlalr/examples/qparser/qparser.h111
-rw-r--r--util/qlalr/examples/qparser/qparser.pro4
18 files changed, 1565 insertions, 0 deletions
diff --git a/util/qlalr/examples/dummy-xml/dummy-xml.pro b/util/qlalr/examples/dummy-xml/dummy-xml.pro
new file mode 100644
index 0000000..e54512d
--- /dev/null
+++ b/util/qlalr/examples/dummy-xml/dummy-xml.pro
@@ -0,0 +1,2 @@
+HEADERS += xmltable_p.h
+SOURCES += xmlreader.cpp xmltable.cpp
diff --git a/util/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp b/util/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp
new file mode 100644
index 0000000..54f5e0e
--- /dev/null
+++ b/util/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp
@@ -0,0 +1,83 @@
+
+#include <cstdlib>
+#include <cstdio>
+
+enum Token {
+ EOF_SYMBOL,
+ LEFT_ANGLE,
+ RIGHT_ANGLE,
+ ANY,
+};
+
+static int current_char;
+static int yytoken;
+static bool in_tag = false;
+
+bool parseXmlStream();
+bool parseTagOrWord();
+bool parseTagName();
+
+inline int nextToken()
+{
+ current_char = fgetc(stdin);
+ if (current_char == EOF) {
+ return (yytoken = EOF_SYMBOL);
+ } else if (current_char == '<') {
+ in_tag = true;
+ return (yytoken = LEFT_ANGLE);
+ } else if (in_tag && current_char == '>') {
+ in_tag = false;
+ return (yytoken = RIGHT_ANGLE);
+ }
+ return (yytoken = ANY);
+}
+
+bool parse()
+{
+ nextToken();
+ return parseXmlStream();
+}
+
+bool parseXmlStream()
+{
+ while (parseTagOrWord())
+ ;
+
+ return true;
+}
+
+bool parseTagOrWord()
+{
+ if (yytoken == LEFT_ANGLE) {
+ nextToken();
+ if (! parseTagName())
+ return false;
+ if (yytoken != RIGHT_ANGLE)
+ return false;
+ nextToken();
+
+ fprintf (stderr, "*** found a tag\n");
+
+ } else if (yytoken == ANY) {
+ nextToken();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool parseTagName()
+{
+ while (yytoken == ANY)
+ nextToken();
+
+ return true;
+}
+
+int main()
+{
+ if (parse())
+ printf("OK\n");
+ else
+ printf("KO\n");
+}
diff --git a/util/qlalr/examples/dummy-xml/xml.g b/util/qlalr/examples/dummy-xml/xml.g
new file mode 100644
index 0000000..212c829
--- /dev/null
+++ b/util/qlalr/examples/dummy-xml/xml.g
@@ -0,0 +1,202 @@
+
+%parser XMLTable
+
+%impl xmlreader.cpp
+
+%token LEFT_ANGLE
+%token RIGHT_ANGLE
+%token ANY
+
+%start XmlStream
+
+/.
+#ifndef XMLREADER_H
+#define XMLREADER_H
+
+#include <QtCore>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include "$header"
+
+class XMLReader: protected $table
+{
+public:
+ XMLReader(const QByteArray &bytes);
+ ~XMLReader();
+
+ bool parse();
+
+ inline int nextToken()
+ {
+ switch (*bufptr++) {
+ case '\0':
+ return EOF_SYMBOL;
+
+ case '<':
+ in_tag = true;
+ return LEFT_ANGLE;
+
+ case '>':
+ if (! in_tag)
+ break;
+ in_tag = false;
+ return RIGHT_ANGLE;
+ break;
+
+ } // switch
+
+ return ANY;
+ }
+
+protected:
+ inline void reallocateStack();
+
+ inline int &sym(int index)
+ { return stack [tos + index - 1].ival; }
+
+protected:
+ int tos;
+ int stack_size;
+
+ struct StackItem {
+ int state;
+ int ival;
+ };
+
+ QVarLengthArray<StackItem> stack;
+ unsigned in_tag: 1;
+ QByteArray bytes;
+ const char *bufptr;
+};
+
+inline void XMLReader::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ stack.resize (stack_size);
+}
+
+#endif // XMLREADER_H
+
+XMLReader::XMLReader(const QByteArray &bytes):
+ tos(0),
+ stack_size(0),
+ bytes(bytes)
+{
+ bufptr = bytes.constData();
+}
+
+XMLReader::~XMLReader()
+{
+}
+
+bool XMLReader::parse()
+{
+ const int INITIAL_STATE = 0;
+
+ in_tag = 0;
+ bufptr = bytes.constData();
+
+ int yytoken = -1;
+ reallocateStack();
+
+ tos = 0;
+ stack [++tos].state = INITIAL_STATE;
+
+ while (true)
+ {
+ const int state = stack [tos].state;
+
+ if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
+ yytoken = nextToken();
+
+ int act = t_action (state, yytoken);
+
+ if (act == ACCEPT_STATE)
+ return true;
+
+ else if (act > 0)
+ {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ stack [tos].ival = *bufptr; // ### save the token value here
+ stack [tos].state = act;
+ yytoken = -1;
+ }
+
+ else if (act < 0)
+ {
+ int r = - act - 1;
+
+ tos -= rhs [r];
+ act = stack [tos++].state;
+
+ switch (r) {
+./
+
+
+
+
+XmlStream: TagOrWord ;
+XmlStream: XmlStream TagOrWord ;
+
+TagOrWord: Tag ;
+TagOrWord: ANY ;
+
+Tag: LEFT_ANGLE TagName RIGHT_ANGLE ;
+/.
+ case $rule_number: {
+ fprintf (stderr, "*** found a tag\n");
+ } break;
+./
+
+TagName: ANY ;
+TagName: TagName ANY ;
+
+
+/.
+ } // switch
+
+ stack [tos].state = nt_action (act, lhs [r] - TERMINAL_COUNT);
+ }
+
+ else
+ {
+ // ### ERROR RECOVERY HERE
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+
+/////////////////////////////
+// entry point
+/////////////////////////////
+int main(int, char *argv[])
+{
+ QFile f (argv[1]);
+
+ if (f.open(QFile::ReadOnly)) {
+ QByteArray contents = f.readAll();
+ XMLReader parser (contents);
+
+ if (parser.parse())
+ printf ("OK\n");
+ else
+ printf ("KO\n");
+ }
+}
+
+
+
+
+./
+
diff --git a/util/qlalr/examples/glsl/build.sh b/util/qlalr/examples/glsl/build.sh
new file mode 100644
index 0000000..0316911
--- /dev/null
+++ b/util/qlalr/examples/glsl/build.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+${FLEX-flex} -oglsl-lex.incl glsl-lex.l
+${QLALR-qlalr} glsl.g
+
+qmake
+make
diff --git a/util/qlalr/examples/glsl/glsl b/util/qlalr/examples/glsl/glsl
new file mode 100755
index 0000000..c19018f
--- /dev/null
+++ b/util/qlalr/examples/glsl/glsl
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+me=$(dirname $0)
+${CPP-cpp} -nostdinc $* | $me/glsl.bin
diff --git a/util/qlalr/examples/glsl/glsl-lex.l b/util/qlalr/examples/glsl/glsl-lex.l
new file mode 100644
index 0000000..1e07c3b
--- /dev/null
+++ b/util/qlalr/examples/glsl/glsl-lex.l
@@ -0,0 +1,201 @@
+
+%{
+#include <cassert>
+#define YY_DECL int GLSLParser::nextToken()
+%}
+
+%option noyywrap
+
+hex [0-9a-fA-F]
+dec [1-9][0-9]*
+oct [0-7]
+digit [0-9]
+
+fract {digit}*\.{digit}+|{digit}+\.
+exp [eE][+-]?{digit}+
+
+hexfract {hex}*\.{hex}+|{hex}+\.
+binexp [pP][+-]?{digit}+
+
+icst ({dec}|0{oct}*|0[xX]{hex}+)
+
+%%
+
+[\n] { ++context.line; }
+[ \t\r]+ { /* skip */ }
+
+"+=" { return ADD_ASSIGN; }
+"&" { return AMPERSAND; }
+"&=" { return AND_ASSIGN; }
+"&&" { return AND_OP; }
+"attribute" { return ATTRIBUTE; }
+"!" { return BANG; }
+"bool" { return BOOL; }
+"true" { return BOOLCONSTANT; }
+"false" { return BOOLCONSTANT; }
+"break" { return BREAK; }
+"bvec2" { return BVEC2; }
+"bvec3" { return BVEC3; }
+"bvec4" { return BVEC4; }
+":" { return COLON; }
+"," { return COMMA; }
+"const" { return CONST; }
+"continue" { return CONTINUE; }
+"-" { return DASH; }
+"--" { return DEC_OP; }
+"discard" { return DISCARD; }
+"/=" { return DIV_ASSIGN; }
+"do" { return DO; }
+"." { return DOT; }
+"else" { return ELSE; }
+"=" { return EQUAL; }
+"==" { return EQ_OP; }
+"float" { return FLOAT; }
+"for" { return FOR; }
+">=" { return GE_OP; }
+"if" { return IF; }
+"in" { return IN; }
+"++" { return INC_OP; }
+"inout" { return INOUT; }
+"int" { return INT; }
+"ivec2" { return IVEC2; }
+"ivec3" { return IVEC3; }
+"ivec4" { return IVEC4; }
+"<" { return LEFT_ANGLE; }
+"<<=" { return LEFT_ASSIGN; }
+"{" { return LEFT_BRACE; }
+"[" { return LEFT_BRACKET; }
+"<<" { return LEFT_OP; }
+"(" { return LEFT_PAREN; }
+"<=" { return LE_OP; }
+"mat2" { return MAT2; }
+"mat3" { return MAT3; }
+"mat4" { return MAT4; }
+"%=" { return MOD_ASSIGN; }
+"*=" { return MUL_ASSIGN; }
+"!=" { return NE_OP; }
+"|=" { return OR_ASSIGN; }
+"||" { return OR_OP; }
+"out" { return OUT; }
+"%" { return PERCENT; }
+"+" { return PLUS; }
+"?" { return QUESTION; }
+"return" { return RETURN; }
+">" { return RIGHT_ANGLE; }
+">>=" { return RIGHT_ASSIGN; }
+"}" { return RIGHT_BRACE; }
+"]" { return RIGHT_BRACKET; }
+">>" { return RIGHT_OP; }
+")" { return RIGHT_PAREN; }
+"sampler1D" { return SAMPLER1D; }
+"sampler1DShadow" { return SAMPLER1DSHADOW; }
+"sampler2D" { return SAMPLER2D; }
+"sampler2DShadow" { return SAMPLER2DSHADOW; }
+"sampler3D" { return SAMPLER3D; }
+"samplerCube" { return SAMPLERCUBE; }
+";" { return SEMICOLON; }
+"/" { return SLASH; }
+"*" { return STAR; }
+"struct" { return STRUCT; }
+"-=" { return SUB_ASSIGN; }
+"~" { return TILDE; }
+"uniform" { return UNIFORM; }
+"varying" { return VARYING; }
+"vec2" { return VEC2; }
+"vec3" { return VEC3; }
+"vec4" { return VEC4; }
+"|" { return VERTICAL_BAR; }
+"void" { return VOID; }
+"while" { return WHILE; }
+"^=" { return XOR_ASSIGN; }
+"^" { return XOR_OP; }
+
+#[ \t]+[0-9]+.* {
+ char *eptr = 0;
+ context.line = (int) strtod(&yytext[1], &eptr);
+ QString fn = QString::fromUtf8(eptr).trimmed();
+ if (fn.length() > 2)
+ context.fileName = fn.mid(1, fn.length()-2);
+}
+
+#.* {
+ /* skip */
+}
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+ yylval.s = intern (yytext);
+
+ if (isTypename (yylval.s))
+ return TYPE_NAME;
+
+ return IDENTIFIER;
+}
+
+{icst} {
+ yylval.i = (int) strtol (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}[uU] {
+ yylval.u = (unsigned) strtoul (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}[uU][lL] {
+ yylval.ul = strtoul (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}[lL][uU] {
+ yylval.ul = strtoul (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}[lL] {
+ yylval.l = strtol (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}[uU](ll|LL) {
+ yylval.l = strtoull (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}(ll|LL) {
+ yylval.l = strtoll (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{icst}(ll|LL)[uU] {
+ yylval.l = strtoull (yytext, 0, 0);
+ return INTCONSTANT;
+}
+
+{fract}{exp}?[flFL]? {
+ yylval.f = strtof (yytext, 0);
+ return FLOATCONSTANT;
+}
+
+{digit}+{exp}[flFL]? {
+ yylval.f = strtof (yytext, 0);
+ return FLOATCONSTANT;
+}
+
+0[xX]{hexfract}{binexp}[flFL]? {
+ yylval.f = strtof (yytext, 0);
+ return FLOATCONSTANT;
+}
+
+0[xX]{hex}+{binexp}[flFL]? {
+ yylval.f = strtof (yytext, 0);
+ return FLOATCONSTANT;
+}
+
+. {
+ fprintf (stderr, "invalid char: %d\n", yytext [0]);
+ return ERROR;
+}
+
+
+%%
+
diff --git a/util/qlalr/examples/glsl/glsl.g b/util/qlalr/examples/glsl/glsl.g
new file mode 100644
index 0000000..3f3a3ad
--- /dev/null
+++ b/util/qlalr/examples/glsl/glsl.g
@@ -0,0 +1,621 @@
+
+%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
+%start translation_unit
+
+
+/:
+
+#include <QtCore>
+
+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<QString> string_repository;
+ QSet<const QString*> 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<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+}
+
+:/
+
+
+/.
+
+GLSLParser::GLSLParser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0)
+{
+}
+
+GLSLParser::~GLSLParser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(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 ::= VOID ;
+type_specifier ::= FLOAT ;
+type_specifier ::= INT ;
+type_specifier ::= BOOL ;
+type_specifier ::= VEC2 ;
+type_specifier ::= VEC3 ;
+type_specifier ::= VEC4 ;
+type_specifier ::= BVEC2 ;
+type_specifier ::= BVEC3 ;
+type_specifier ::= BVEC4 ;
+type_specifier ::= IVEC2 ;
+type_specifier ::= IVEC3 ;
+type_specifier ::= IVEC4 ;
+type_specifier ::= MAT2 ;
+type_specifier ::= MAT3 ;
+type_specifier ::= MAT4 ;
+type_specifier ::= SAMPLER1D ;
+type_specifier ::= SAMPLER2D ;
+type_specifier ::= SAMPLER3D ;
+type_specifier ::= SAMPLERCUBE ;
+type_specifier ::= SAMPLER1DSHADOW ;
+type_specifier ::= SAMPLER2DSHADOW ;
+type_specifier ::= struct_specifier ;
+type_specifier ::= TYPE_NAME ;
+
+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";
+}
+
+./
diff --git a/util/qlalr/examples/glsl/glsl.pro b/util/qlalr/examples/glsl/glsl.pro
new file mode 100644
index 0000000..8ac775f
--- /dev/null
+++ b/util/qlalr/examples/glsl/glsl.pro
@@ -0,0 +1,4 @@
+QT = core
+TARGET = glsl.bin
+SOURCES += glsl.cpp
+
diff --git a/util/qlalr/examples/lambda/COMPILE b/util/qlalr/examples/lambda/COMPILE
new file mode 100644
index 0000000..3226ec9
--- /dev/null
+++ b/util/qlalr/examples/lambda/COMPILE
@@ -0,0 +1,3 @@
+qlalr lambda.g
+qmake
+make
diff --git a/util/qlalr/examples/lambda/lambda.g b/util/qlalr/examples/lambda/lambda.g
new file mode 100644
index 0000000..2fb9594
--- /dev/null
+++ b/util/qlalr/examples/lambda/lambda.g
@@ -0,0 +1,41 @@
+
+-- lambda calculus
+
+%decl lambda.h
+
+%token LPAREN
+%token RPAREN
+%token ID
+%token FUN
+%token DOT
+
+%nonassoc SHIFT_THERE
+%nonassoc LPAREN RPAREN ID FUN DOT
+%nonassoc REDUCE_HERE
+
+%start Expr
+
+/:
+enum {
+:/
+
+
+Expr ::= ID %prec SHIFT_THERE ;
+/: Symbol = $rule_number,
+:/
+
+Expr ::= LPAREN Expr RPAREN %prec SHIFT_THERE ;
+/: SubExpression = $rule_number,
+:/
+
+Expr ::= Expr Expr %prec REDUCE_HERE ;
+/: Appl = $rule_number,
+:/
+
+Expr ::= FUN ID DOT Expr %prec SHIFT_THERE ;
+/: Abstr = $rule_number,
+:/
+
+/:};
+:/
+
diff --git a/util/qlalr/examples/lambda/lambda.pro b/util/qlalr/examples/lambda/lambda.pro
new file mode 100644
index 0000000..dfe4824
--- /dev/null
+++ b/util/qlalr/examples/lambda/lambda.pro
@@ -0,0 +1,3 @@
+HEADERS += lambda.h parser_table_p.h
+SOURCES += main.cpp parser_table.cpp
+QT = core
diff --git a/util/qlalr/examples/lambda/main.cpp b/util/qlalr/examples/lambda/main.cpp
new file mode 100644
index 0000000..c70f9a5
--- /dev/null
+++ b/util/qlalr/examples/lambda/main.cpp
@@ -0,0 +1,160 @@
+
+#include "lambda.h"
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include "parser_table_p.h"
+
+class Parser: protected parser_table
+{
+public:
+ union Value {
+ int ival;
+ // ### more...
+ };
+
+public:
+ Parser();
+ ~Parser();
+
+ bool parse();
+
+protected:
+ inline void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ int nextToken();
+ void consumeRule(int ruleno);
+
+protected:
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ int current_char;
+ unsigned in_tag: 1;
+};
+
+inline void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (::realloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (::realloc(state_stack, stack_size * sizeof(int)));
+}
+
+Parser::Parser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ ::free(sym_stack);
+ ::free(state_stack);
+ }
+}
+
+bool Parser::parse()
+{
+ const int INITIAL_STATE = 0;
+
+ current_char = 0;
+ in_tag = 0;
+
+ int yytoken = -1;
+ reallocateStack();
+
+ 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].ival = current_char; // ### save the token value here
+ state_stack [tos] = act;
+ yytoken = -1;
+ }
+
+ else if (act < 0)
+ {
+ int r = - act - 1;
+
+ tos -= rhs [r];
+ act = state_stack [tos++];
+ consumeRule (r);
+ state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
+ }
+
+ else
+ break;
+ }
+
+ return false;
+}
+
+
+int Parser::nextToken()
+{
+ static int tokens[] = { ID, ID, ID, EOF_SYMBOL };
+ static int *tk = tokens;
+
+ return *tk++;
+}
+
+void Parser::consumeRule(int ruleno)
+{
+ switch (ruleno) {
+ case Symbol:
+ printf("symbol\n");
+ break;
+ case SubExpression:
+ printf("sub-expr\n");
+ break;
+ case Appl:
+ printf("appl\n");
+ break;
+ case Abstr:
+ printf("abstr\n");
+ break;
+ }
+}
+
+/////////////////////////////
+// entry point
+/////////////////////////////
+int main()
+{
+ Parser parser;
+
+ if (parser.parse())
+ printf ("OK\n");
+ else
+ printf ("KO\n");
+}
+
+
diff --git a/util/qlalr/examples/qparser/COMPILE b/util/qlalr/examples/qparser/COMPILE
new file mode 100644
index 0000000..4aad300
--- /dev/null
+++ b/util/qlalr/examples/qparser/COMPILE
@@ -0,0 +1,3 @@
+qlalr calc.g
+qmake
+make
diff --git a/util/qlalr/examples/qparser/calc.g b/util/qlalr/examples/qparser/calc.g
new file mode 100644
index 0000000..24371d4
--- /dev/null
+++ b/util/qlalr/examples/qparser/calc.g
@@ -0,0 +1,93 @@
+
+%parser calc_grammar
+%decl calc_parser.h
+%impl calc_parser.cpp
+
+%token_prefix Token_
+%token number
+%token lparen
+%token rparen
+%token plus
+%token minus
+
+%start Goal
+
+/:
+#ifndef CALC_PARSER_H
+#define CALC_PARSER_H
+
+#include "qparser.h"
+#include "calc_grammar_p.h"
+
+class CalcParser: public QParser<CalcParser, $table>
+{
+public:
+ int nextToken();
+ void consumeRule(int ruleno);
+};
+
+#endif // CALC_PARSER_H
+:/
+
+
+
+
+
+/.
+#include "calc_parser.h"
+
+#include <QtDebug>
+#include <cstdlib>
+
+void CalcParser::consumeRule(int ruleno)
+ {
+ switch (ruleno) {
+./
+
+Goal: Expression ;
+/.
+case $rule_number:
+ qDebug() << "value:" << sym(1);
+ break;
+./
+
+PrimaryExpression: number ;
+PrimaryExpression: lparen Expression rparen ;
+/.
+case $rule_number:
+ sym(1) = sym (2);
+ break;
+./
+
+Expression: PrimaryExpression ;
+
+Expression: Expression plus PrimaryExpression;
+/.
+case $rule_number:
+ sym(1) += sym (3);
+ break;
+./
+
+Expression: Expression minus PrimaryExpression;
+/.
+case $rule_number:
+ sym(1) -= sym (3);
+ break;
+./
+
+
+
+/.
+ } // switch
+}
+
+#include <cstdio>
+
+int main()
+{
+ CalcParser p;
+
+ if (p.parse())
+ printf("ok\n");
+}
+./
diff --git a/util/qlalr/examples/qparser/calc.l b/util/qlalr/examples/qparser/calc.l
new file mode 100644
index 0000000..95181d5
--- /dev/null
+++ b/util/qlalr/examples/qparser/calc.l
@@ -0,0 +1,20 @@
+
+%option noyywrap
+
+%{
+#include "calc_parser.h"
+#include <cstdlib>
+
+#define YY_DECL int CalcParser::nextToken()
+%}
+
+%%
+
+[ \t\n] { /* eat me */ }
+[0-9]+ { sym(1) = atoi (yytext); return Token_number; }
+"(" { return Token_lparen; }
+")" { return Token_rparen; }
+"+" { return Token_plus; }
+"-" { return Token_minus; }
+
+%%
diff --git a/util/qlalr/examples/qparser/qparser.cpp b/util/qlalr/examples/qparser/qparser.cpp
new file mode 100644
index 0000000..5a18ee2
--- /dev/null
+++ b/util/qlalr/examples/qparser/qparser.cpp
@@ -0,0 +1,3 @@
+
+#include "qparser.h"
+
diff --git a/util/qlalr/examples/qparser/qparser.h b/util/qlalr/examples/qparser/qparser.h
new file mode 100644
index 0000000..e3ff61d
--- /dev/null
+++ b/util/qlalr/examples/qparser/qparser.h
@@ -0,0 +1,111 @@
+#ifndef QPARSER_H
+#define QPARSER_H
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QVarLengthArray>
+
+template <typename _Parser, typename _Table, typename _Value = int>
+class QParser: protected _Table
+{
+public:
+ QParser();
+ ~QParser();
+
+ bool parse();
+
+ inline _Value &sym(int index);
+
+private:
+ inline int nextToken()
+ {
+ return static_cast<_Parser*> (this)->nextToken();
+ }
+
+ inline void consumeRule(int rule)
+ {
+ static_cast<_Parser*> (this)->consumeRule(rule);
+ }
+
+ enum { DefaultStackSize = 128 };
+
+ struct Data: public QSharedData
+ {
+ Data(): stackSize (DefaultStackSize), tos (0) {}
+
+ QVarLengthArray<int, DefaultStackSize> stateStack;
+ QVarLengthArray<_Value, DefaultStackSize> parseStack;
+ int stackSize;
+ int tos;
+
+ void reallocateStack() {
+ stackSize <<= 1;
+ stateStack.resize(stackSize);
+ parseStack.resize(stackSize);
+ }
+ };
+
+ QSharedDataPointer<Data> d;
+};
+
+template <typename _Parser, typename _Table, typename _Value>
+inline _Value &QParser<_Parser, _Table, _Value>::sym(int n)
+{
+ return d->parseStack [d->tos + n - 1];
+}
+
+template <typename _Parser, typename _Table, typename _Value>
+QParser<_Parser, _Table, _Value>::QParser():
+ d(new Data())
+{
+}
+
+template <typename _Parser, typename _Table, typename _Value>
+QParser<_Parser, _Table, _Value>::~QParser()
+{
+}
+
+template <typename _Parser, typename _Table, typename _Value>
+bool QParser<_Parser, _Table, _Value>::parse()
+{
+ const int INITIAL_STATE = 0;
+
+ d->tos = 0;
+ d->reallocateStack();
+
+ int act = d->stateStack[++d->tos] = INITIAL_STATE;
+ int token = -1;
+
+ forever {
+ if (token == -1 && - _Table::TERMINAL_COUNT != _Table::action_index[act])
+ token = nextToken();
+
+ act = _Table::t_action(act, token);
+
+ if (d->stateStack[d->tos] == _Table::ACCEPT_STATE)
+ return true;
+
+ else if (act > 0) {
+ if (++d->tos == d->stackSize)
+ d->reallocateStack();
+
+ d->parseStack[d->tos] = d->parseStack[d->tos - 1];
+ d->stateStack[d->tos] = act;
+ token = -1;
+ }
+
+ else if (act < 0) {
+ int r = - act - 1;
+ d->tos -= _Table::rhs[r];
+ act = d->stateStack[d->tos++];
+ consumeRule(r);
+ act = d->stateStack[d->tos] = _Table::nt_action(act, _Table::lhs[r] - _Table::TERMINAL_COUNT);
+ }
+
+ else break;
+ }
+
+ return false;
+}
+
+
+#endif // QPARSER_H
diff --git a/util/qlalr/examples/qparser/qparser.pro b/util/qlalr/examples/qparser/qparser.pro
new file mode 100644
index 0000000..938e336
--- /dev/null
+++ b/util/qlalr/examples/qparser/qparser.pro
@@ -0,0 +1,4 @@
+QT = core
+HEADERS += calc_grammar_p.h calc_parser.h qparser.h
+SOURCES += calc_grammar.cpp calc_parser.cpp qparser.cpp
+LEXSOURCES += calc.l