diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /util/qlalr/examples | |
download | Qt-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.pro | 2 | ||||
-rw-r--r-- | util/qlalr/examples/dummy-xml/ll/dummy-xml-ll.cpp | 83 | ||||
-rw-r--r-- | util/qlalr/examples/dummy-xml/xml.g | 202 | ||||
-rw-r--r-- | util/qlalr/examples/glsl/build.sh | 7 | ||||
-rwxr-xr-x | util/qlalr/examples/glsl/glsl | 4 | ||||
-rw-r--r-- | util/qlalr/examples/glsl/glsl-lex.l | 201 | ||||
-rw-r--r-- | util/qlalr/examples/glsl/glsl.g | 621 | ||||
-rw-r--r-- | util/qlalr/examples/glsl/glsl.pro | 4 | ||||
-rw-r--r-- | util/qlalr/examples/lambda/COMPILE | 3 | ||||
-rw-r--r-- | util/qlalr/examples/lambda/lambda.g | 41 | ||||
-rw-r--r-- | util/qlalr/examples/lambda/lambda.pro | 3 | ||||
-rw-r--r-- | util/qlalr/examples/lambda/main.cpp | 160 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/COMPILE | 3 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/calc.g | 93 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/calc.l | 20 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/qparser.cpp | 3 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/qparser.h | 111 | ||||
-rw-r--r-- | util/qlalr/examples/qparser/qparser.pro | 4 |
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 |