├── .qmake.conf ├── .tag ├── qlalr.pro ├── examples ├── lambda │ ├── COMPILE │ ├── lambda.pro │ ├── lambda.g │ └── main.cpp ├── qparser │ ├── COMPILE │ ├── qparser.pro │ ├── qparser.cpp │ ├── calc.l │ ├── calc.g │ └── qparser.h ├── glsl │ ├── glsl.pro │ ├── glsl │ ├── build.sh │ ├── glsl-lex.l │ └── glsl.g └── dummy-xml │ ├── dummy-xml.pro │ ├── ll │ └── dummy-xml-ll.cpp │ └── xml.g ├── doc ├── src │ ├── images │ │ └── qt-logo.png │ ├── classic.css │ └── qlalr.qdoc ├── global │ ├── qt-html-templates-offline.qdocconf │ ├── qt-module-defaults.qdocconf │ └── style │ │ └── offline.css └── qlalr.qdocconf └── src ├── src.pro ├── dotgraph.h ├── parsetable.h ├── compress.h ├── cppgenerator.h ├── recognizer.h ├── dotgraph.cpp ├── grammar_p.h ├── parsetable.cpp ├── grammar.cpp ├── main.cpp ├── compress.cpp ├── lalr.h ├── recognizer.cpp ├── lalr.g └── lalr.cpp /.qmake.conf: -------------------------------------------------------------------------------- 1 | load(qt_build_config) 2 | -------------------------------------------------------------------------------- /.tag: -------------------------------------------------------------------------------- 1 | 4071d86e82b299f26e335a7faf662b5a676e2279 2 | -------------------------------------------------------------------------------- /qlalr.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS = src 3 | -------------------------------------------------------------------------------- /examples/lambda/COMPILE: -------------------------------------------------------------------------------- 1 | qlalr lambda.g 2 | qmake 3 | make 4 | -------------------------------------------------------------------------------- /examples/qparser/COMPILE: -------------------------------------------------------------------------------- 1 | qlalr calc.g 2 | qmake 3 | make 4 | -------------------------------------------------------------------------------- /examples/glsl/glsl.pro: -------------------------------------------------------------------------------- 1 | QT = core 2 | TARGET = glsl.bin 3 | SOURCES += glsl.cpp 4 | 5 | -------------------------------------------------------------------------------- /doc/src/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qt/qlalr/master/doc/src/images/qt-logo.png -------------------------------------------------------------------------------- /examples/dummy-xml/dummy-xml.pro: -------------------------------------------------------------------------------- 1 | HEADERS += xmltable_p.h 2 | SOURCES += xmlreader.cpp xmltable.cpp 3 | -------------------------------------------------------------------------------- /examples/glsl/glsl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | me=$(dirname $0) 4 | ${CPP-cpp} -nostdinc $* | $me/glsl.bin 5 | -------------------------------------------------------------------------------- /examples/lambda/lambda.pro: -------------------------------------------------------------------------------- 1 | HEADERS += lambda.h parser_table_p.h 2 | SOURCES += main.cpp parser_table.cpp 3 | QT = core 4 | -------------------------------------------------------------------------------- /examples/qparser/qparser.pro: -------------------------------------------------------------------------------- 1 | QT = core 2 | HEADERS += calc_grammar_p.h calc_parser.h qparser.h 3 | SOURCES += calc_grammar.cpp calc_parser.cpp qparser.cpp 4 | LEXSOURCES += calc.l 5 | -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | 2 | TEMPLATE = app 3 | QT = core 4 | CONFIG += console 5 | TARGET = qlalr 6 | mac:CONFIG -= app_bundle 7 | 8 | SOURCES += compress.cpp \ 9 | cppgenerator.cpp \ 10 | dotgraph.cpp \ 11 | lalr.cpp \ 12 | main.cpp \ 13 | parsetable.cpp \ 14 | recognizer.cpp \ 15 | grammar.cpp 16 | 17 | HEADERS += compress.h \ 18 | cppgenerator.h \ 19 | dotgraph.h \ 20 | lalr.h \ 21 | parsetable.h \ 22 | grammar_p.h 23 | 24 | OTHER_FILES = lalr.g 25 | -------------------------------------------------------------------------------- /doc/src/classic.css: -------------------------------------------------------------------------------- 1 | h3.fn,span.fn 2 | { 3 | margin-left: 1cm; 4 | text-indent: -1cm; 5 | } 6 | 7 | a:link 8 | { 9 | color: #004faf; 10 | text-decoration: none 11 | } 12 | 13 | a:visited 14 | { 15 | color: #672967; 16 | text-decoration: none 17 | } 18 | 19 | td.postheader 20 | { 21 | font-family: sans-serif 22 | } 23 | 24 | tr.address 25 | { 26 | font-family: sans-serif 27 | } 28 | 29 | body 30 | { 31 | background: #ffffff; 32 | color: black 33 | } 34 | 35 | table tr.odd { 36 | background: #f0f0f0; 37 | color: black; 38 | } 39 | 40 | table tr.even { 41 | background: #e4e4e4; 42 | color: black; 43 | } 44 | 45 | table.annotated { 46 | border-spacing: 0px; 47 | } 48 | 49 | table.annotated th { 50 | font-weight: bold; 51 | padding: 3px; 52 | text-align: left 53 | } 54 | 55 | table.annotated td { 56 | padding: 3px; 57 | } 58 | 59 | table tr pre 60 | { 61 | padding-top: none; 62 | padding-bottom: none; 63 | padding-left: none; 64 | padding-right: none; 65 | border: none; 66 | background: none 67 | } 68 | 69 | tr.qt-style 70 | { 71 | background: #a2c511; 72 | color: black 73 | } 74 | 75 | body pre 76 | { 77 | padding: 0.2em; 78 | border: #e7e7e7 1px solid; 79 | background: #f1f1f1; 80 | color: black 81 | } 82 | 83 | span.preprocessor, span.preprocessor a 84 | { 85 | color: darkblue; 86 | } 87 | 88 | span.comment 89 | { 90 | color: darkred; 91 | font-style: italic 92 | } 93 | 94 | span.string,span.char 95 | { 96 | color: darkgreen; 97 | } 98 | -------------------------------------------------------------------------------- /doc/global/qt-html-templates-offline.qdocconf: -------------------------------------------------------------------------------- 1 | # 2 | # W A R N I N G 3 | # ------------- 4 | # 5 | # A common HTML template for modules in this repository. 6 | # This template is common among the Qt 5 modules. 7 | # 8 | # A change in this template must be replicated in all of the repositories. 9 | # 10 | # We mean it. 11 | # 12 | 13 | HTML.templatedir = ../../../doc 14 | 15 | HTML.nobreadcrumbs = "true" 16 | 17 | HTML.stylesheets = global/style/offline.css 18 | 19 | HTML.headerstyles = \ 20 | " \n" 21 | 22 | HTML.endheader = \ 23 | "\n" \ 24 | 25 | HTML.footer = \ 26 | "
\n" \ 27 | "

\n" \ 28 | " © 2013 Digia Plc and/or its\n" \ 29 | " subsidiaries. Documentation contributions included herein are the copyrights of\n" \ 30 | " their respective owners.

\n" \ 31 | "
\n" \ 32 | "

\n" \ 33 | " The documentation provided herein is licensed under the terms of the\n" \ 34 | " GNU Free Documentation\n" \ 35 | " License version 1.3 as published by the Free Software Foundation.

\n" \ 36 | "

\n" \ 37 | " Documentation sources may be obtained from \n" \ 38 | " www.qt-project.org.

\n" \ 39 | "
\n" \ 40 | "

\n" \ 41 | " Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \ 42 | " in Finland and/or other countries worldwide. All other trademarks are property\n" \ 43 | " of their respective owners. Privacy Policy

\n" \ 45 | "
\n" \ 46 | -------------------------------------------------------------------------------- /examples/qparser/qparser.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the QLALR module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #include "qparser.h" 43 | 44 | -------------------------------------------------------------------------------- /examples/glsl/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ############################################################################# 3 | ## 4 | ## Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 5 | ## Contact: http://www.qt-project.org/legal 6 | ## 7 | ## This file is the build configuration utility of the Qt Toolkit. 8 | ## 9 | ## $QT_BEGIN_LICENSE:LGPL$ 10 | ## Commercial License Usage 11 | ## Licensees holding valid commercial Qt licenses may use this file in 12 | ## accordance with the commercial license agreement provided with the 13 | ## Software or, alternatively, in accordance with the terms contained in 14 | ## a written agreement between you and Digia. For licensing terms and 15 | ## conditions see http://qt.digia.com/licensing. For further information 16 | ## use the contact form at http://qt.digia.com/contact-us. 17 | ## 18 | ## GNU Lesser General Public License Usage 19 | ## Alternatively, this file may be used under the terms of the GNU Lesser 20 | ## General Public License version 2.1 as published by the Free Software 21 | ## Foundation and appearing in the file LICENSE.LGPL included in the 22 | ## packaging of this file. Please review the following information to 23 | ## ensure the GNU Lesser General Public License version 2.1 requirements 24 | ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 | ## 26 | ## In addition, as a special exception, Digia gives you certain additional 27 | ## rights. These rights are described in the Digia Qt LGPL Exception 28 | ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 | ## 30 | ## GNU General Public License Usage 31 | ## Alternatively, this file may be used under the terms of the GNU 32 | ## General Public License version 3.0 as published by the Free Software 33 | ## Foundation and appearing in the file LICENSE.GPL included in the 34 | ## packaging of this file. Please review the following information to 35 | ## ensure the GNU General Public License version 3.0 requirements will be 36 | ## met: http://www.gnu.org/copyleft/gpl.html. 37 | ## 38 | ## 39 | ## $QT_END_LICENSE$ 40 | ## 41 | ############################################################################# 42 | 43 | ${FLEX-flex} -oglsl-lex.incl glsl-lex.l 44 | ${QLALR-qlalr} glsl.g 45 | 46 | qmake 47 | make 48 | -------------------------------------------------------------------------------- /src/dotgraph.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef DOTGRAPH_H 43 | #define DOTGRAPH_H 44 | 45 | QT_FORWARD_DECLARE_CLASS(QTextStream); 46 | class Automaton; 47 | 48 | class DotGraph 49 | { 50 | public: 51 | DotGraph (QTextStream &out); 52 | 53 | void operator () (Automaton *a); 54 | 55 | private: 56 | QTextStream &out; 57 | }; 58 | 59 | #endif // DOTGRAPH_H 60 | -------------------------------------------------------------------------------- /src/parsetable.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef PARSETABLE_H 43 | #define PARSETABLE_H 44 | 45 | QT_FORWARD_DECLARE_CLASS(QTextStream); 46 | class Automaton; 47 | 48 | class ParseTable 49 | { 50 | public: 51 | ParseTable (QTextStream &out); 52 | 53 | void operator () (Automaton *a); 54 | 55 | private: 56 | QTextStream &out; 57 | }; 58 | 59 | #endif // PARSETABLE_H 60 | -------------------------------------------------------------------------------- /src/compress.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef COMPRESS_H 43 | #define COMPRESS_H 44 | 45 | #include 46 | 47 | class Compress 48 | { 49 | public: 50 | Compress (); 51 | 52 | void operator () (int *table, int row_count, int column_count); 53 | 54 | public: 55 | QVector index; 56 | QVector info; 57 | QVector check; 58 | }; 59 | 60 | #endif // COMPRESS_H 61 | -------------------------------------------------------------------------------- /examples/qparser/calc.l: -------------------------------------------------------------------------------- 1 | 2 | %option noyywrap 3 | 4 | %{ 5 | /**************************************************************************** 6 | ** 7 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 8 | ** Contact: http://www.qt-project.org/legal 9 | ** 10 | ** This file is part of the QLALR tool of the Qt Toolkit. 11 | ** 12 | ** $QT_BEGIN_LICENSE:LGPL$ 13 | ** Commercial License Usage 14 | ** Licensees holding valid commercial Qt licenses may use this file in 15 | ** accordance with the commercial license agreement provided with the 16 | ** Software or, alternatively, in accordance with the terms contained in 17 | ** a written agreement between you and Digia. For licensing terms and 18 | ** conditions see http://qt.digia.com/licensing. For further information 19 | ** use the contact form at http://qt.digia.com/contact-us. 20 | ** 21 | ** GNU Lesser General Public License Usage 22 | ** Alternatively, this file may be used under the terms of the GNU Lesser 23 | ** General Public License version 2.1 as published by the Free Software 24 | ** Foundation and appearing in the file LICENSE.LGPL included in the 25 | ** packaging of this file. Please review the following information to 26 | ** ensure the GNU Lesser General Public License version 2.1 requirements 27 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 28 | ** 29 | ** In addition, as a special exception, Digia gives you certain additional 30 | ** rights. These rights are described in the Digia Qt LGPL Exception 31 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 32 | ** 33 | ** GNU General Public License Usage 34 | ** Alternatively, this file may be used under the terms of the GNU 35 | ** General Public License version 3.0 as published by the Free Software 36 | ** Foundation and appearing in the file LICENSE.GPL included in the 37 | ** packaging of this file. Please review the following information to 38 | ** ensure the GNU General Public License version 3.0 requirements will be 39 | ** met: http://www.gnu.org/copyleft/gpl.html. 40 | ** 41 | ** 42 | ** $QT_END_LICENSE$ 43 | ** 44 | ****************************************************************************/ 45 | 46 | #include "calc_parser.h" 47 | #include 48 | 49 | #define YY_DECL int CalcParser::nextToken() 50 | %} 51 | 52 | %% 53 | 54 | [ \t\n] { /* eat me */ } 55 | [0-9]+ { sym(1) = atoi (yytext); return Token_number; } 56 | "(" { return Token_lparen; } 57 | ")" { return Token_rparen; } 58 | "+" { return Token_plus; } 59 | "-" { return Token_minus; } 60 | 61 | %% 62 | -------------------------------------------------------------------------------- /examples/lambda/lambda.g: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- 3 | -- Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | -- Contact: http://www.qt-project.org/legal 5 | -- 6 | -- This file is part of the QtCore module of the Qt Toolkit. 7 | -- 8 | -- $QT_BEGIN_LICENSE:LGPL$ 9 | -- Commercial License Usage 10 | -- Licensees holding valid commercial Qt licenses may use this file in 11 | -- accordance with the commercial license agreement provided with the 12 | -- Software or, alternatively, in accordance with the terms contained in 13 | -- a written agreement between you and Digia. For licensing terms and 14 | -- conditions see http://qt.digia.com/licensing. For further information 15 | -- use the contact form at http://qt.digia.com/contact-us. 16 | -- 17 | -- GNU Lesser General Public License Usage 18 | -- Alternatively, this file may be used under the terms of the GNU Lesser 19 | -- General Public License version 2.1 as published by the Free Software 20 | -- Foundation and appearing in the file LICENSE.LGPL included in the 21 | -- packaging of this file. Please review the following information to 22 | -- ensure the GNU Lesser General Public License version 2.1 requirements 23 | -- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | -- 25 | -- In addition, as a special exception, Digia gives you certain additional 26 | -- rights. These rights are described in the Digia Qt LGPL Exception 27 | -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | -- 29 | -- GNU General Public License Usage 30 | -- Alternatively, this file may be used under the terms of the GNU 31 | -- General Public License version 3.0 as published by the Free Software 32 | -- Foundation and appearing in the file LICENSE.GPL included in the 33 | -- packaging of this file. Please review the following information to 34 | -- ensure the GNU General Public License version 3.0 requirements will be 35 | -- met: http://www.gnu.org/copyleft/gpl.html. 36 | -- 37 | -- 38 | -- $QT_END_LICENSE$ 39 | -- 40 | ---------------------------------------------------------------------------- 41 | 42 | -- lambda calculus 43 | 44 | %decl lambda.h 45 | 46 | %token LPAREN 47 | %token RPAREN 48 | %token ID 49 | %token FUN 50 | %token DOT 51 | 52 | %nonassoc SHIFT_THERE 53 | %nonassoc LPAREN RPAREN ID FUN DOT 54 | %nonassoc REDUCE_HERE 55 | 56 | %start Expr 57 | 58 | /: 59 | enum { 60 | :/ 61 | 62 | 63 | Expr ::= ID %prec SHIFT_THERE ; 64 | /: Symbol = $rule_number, 65 | :/ 66 | 67 | Expr ::= LPAREN Expr RPAREN %prec SHIFT_THERE ; 68 | /: SubExpression = $rule_number, 69 | :/ 70 | 71 | Expr ::= Expr Expr %prec REDUCE_HERE ; 72 | /: Appl = $rule_number, 73 | :/ 74 | 75 | Expr ::= FUN ID DOT Expr %prec SHIFT_THERE ; 76 | /: Abstr = $rule_number, 77 | :/ 78 | 79 | /:}; 80 | :/ 81 | 82 | -------------------------------------------------------------------------------- /src/cppgenerator.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the QLALR module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef CPPGENERATOR_H 43 | #define CPPGENERATOR_H 44 | 45 | #include "lalr.h" 46 | #include "compress.h" 47 | 48 | class Grammar; 49 | class Automaton; 50 | class Recognizer; 51 | 52 | class CppGenerator 53 | { 54 | public: 55 | CppGenerator(const Recognizer &p, Grammar &grammar, Automaton &aut, bool verbose): 56 | p (p), 57 | grammar (grammar), 58 | aut (aut), 59 | verbose (verbose), 60 | debug_info (false), 61 | copyright (false) {} 62 | 63 | void operator () (); 64 | 65 | bool debugInfo () const { return debug_info; } 66 | void setDebugInfo (bool d) { debug_info = d; } 67 | 68 | void setCopyright (bool t) { copyright = t; } 69 | 70 | private: 71 | void generateDecl (QTextStream &out); 72 | void generateImpl (QTextStream &out); 73 | 74 | QString debugInfoProt() const; 75 | QString copyrightHeader() const; 76 | QString privateCopyrightHeader() const; 77 | 78 | private: 79 | static QString startIncludeGuard(const QString &fileName); 80 | static QString endIncludeGuard(const QString &fileName); 81 | 82 | const Recognizer &p; 83 | Grammar &grammar; 84 | Automaton &aut; 85 | bool verbose; 86 | int accept_state; 87 | int state_count; 88 | int terminal_count; 89 | int non_terminal_count; 90 | bool debug_info; 91 | bool copyright; 92 | Compress compressed_action; 93 | Compress compressed_goto; 94 | QVector count; 95 | QVector defgoto; 96 | }; 97 | 98 | #endif // CPPGENERATOR_H 99 | -------------------------------------------------------------------------------- /doc/qlalr.qdocconf: -------------------------------------------------------------------------------- 1 | # Run qdoc from the directory that contains this file. 2 | 3 | project = qlalr 4 | description = qlalr Reference Documentation 5 | url = http://qt.nokia.com/doc/ 6 | 7 | language = Cpp 8 | 9 | # sourcedirs = $PWD/src 10 | sourcedirs = src 11 | sources.fileextensions = "*.qdoc" 12 | 13 | exampledirs = ../examples 14 | 15 | imagedirs = src/images 16 | outputdir = html 17 | codeindent = 1 18 | extraimages.HTML = qt-logo 19 | 20 | macro.key = "\\b" 21 | macro.menu = "\\b" 22 | macro.gui = "\\b" 23 | macro.reg.HTML = "®" 24 | macro.raisedaster.HTML = "*" 25 | macro.BR.HTML = "
" 26 | macro.br.HTML = "
" 27 | macro.QD = "\\e{Qt Designer}" 28 | macro.QA = "\\e{Qt Assistant}" 29 | macro.eacute.HTML = "é" 30 | macro.aring.HTML = "å" 31 | macro.oslash.HTML = "ø" 32 | macro.ouml.HTML = "ö" 33 | macro.Auml.HTML = "Ä" 34 | macro.uuml.HTML = "ü" 35 | 36 | HTML.stylesheets = src/classic.css 37 | HTML.postheader = "\n" \ 38 | "\n" \ 39 | "\n" \ 42 | "" \ 43 | "\n" \ 57 | "
" \ 40 | "" \ 41 | "  " \ 44 | "" \ 45 | "Home ·" \ 46 | " " \ 47 | "All Classes ·" \ 48 | " " \ 49 | "Main Classes ·" \ 50 | " " \ 51 | "Grouped Classes ·" \ 52 | " " \ 53 | "Modules ·" \ 54 | " " \ 55 | "Functions" \ 56 | "
" 58 | 59 | HTML.footer = "


\n" \ 60 | "\n" \ 61 | "\n" \ 62 | "\n" \ 63 | "\n" \ 64 | "
Copyright © 2012 Digia Plc and/or its subsidiary(-ies)Trademarks
Qt \\version
" 65 | -------------------------------------------------------------------------------- /examples/qparser/calc.g: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- 3 | -- Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | -- Contact: http://www.qt-project.org/legal 5 | -- 6 | -- This file is part of the QtCore module of the Qt Toolkit. 7 | -- 8 | -- $QT_BEGIN_LICENSE:LGPL$ 9 | -- Commercial License Usage 10 | -- Licensees holding valid commercial Qt licenses may use this file in 11 | -- accordance with the commercial license agreement provided with the 12 | -- Software or, alternatively, in accordance with the terms contained in 13 | -- a written agreement between you and Digia. For licensing terms and 14 | -- conditions see http://qt.digia.com/licensing. For further information 15 | -- use the contact form at http://qt.digia.com/contact-us. 16 | -- 17 | -- GNU Lesser General Public License Usage 18 | -- Alternatively, this file may be used under the terms of the GNU Lesser 19 | -- General Public License version 2.1 as published by the Free Software 20 | -- Foundation and appearing in the file LICENSE.LGPL included in the 21 | -- packaging of this file. Please review the following information to 22 | -- ensure the GNU Lesser General Public License version 2.1 requirements 23 | -- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | -- 25 | -- In addition, as a special exception, Digia gives you certain additional 26 | -- rights. These rights are described in the Digia Qt LGPL Exception 27 | -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | -- 29 | -- GNU General Public License Usage 30 | -- Alternatively, this file may be used under the terms of the GNU 31 | -- General Public License version 3.0 as published by the Free Software 32 | -- Foundation and appearing in the file LICENSE.GPL included in the 33 | -- packaging of this file. Please review the following information to 34 | -- ensure the GNU General Public License version 3.0 requirements will be 35 | -- met: http://www.gnu.org/copyleft/gpl.html. 36 | -- 37 | -- 38 | -- $QT_END_LICENSE$ 39 | -- 40 | ---------------------------------------------------------------------------- 41 | 42 | %parser calc_grammar 43 | %decl calc_parser.h 44 | %impl calc_parser.cpp 45 | 46 | %token_prefix Token_ 47 | %token number 48 | %token lparen 49 | %token rparen 50 | %token plus 51 | %token minus 52 | 53 | %start Goal 54 | 55 | /: 56 | #ifndef CALC_PARSER_H 57 | #define CALC_PARSER_H 58 | 59 | #include "qparser.h" 60 | #include "calc_grammar_p.h" 61 | 62 | class CalcParser: public QParser 63 | { 64 | public: 65 | int nextToken(); 66 | void consumeRule(int ruleno); 67 | }; 68 | 69 | #endif // CALC_PARSER_H 70 | :/ 71 | 72 | 73 | 74 | 75 | 76 | /. 77 | #include "calc_parser.h" 78 | 79 | #include 80 | #include 81 | 82 | void CalcParser::consumeRule(int ruleno) 83 | { 84 | switch (ruleno) { 85 | ./ 86 | 87 | Goal: Expression ; 88 | /. 89 | case $rule_number: 90 | qDebug() << "value:" << sym(1); 91 | break; 92 | ./ 93 | 94 | PrimaryExpression: number ; 95 | PrimaryExpression: lparen Expression rparen ; 96 | /. 97 | case $rule_number: 98 | sym(1) = sym (2); 99 | break; 100 | ./ 101 | 102 | Expression: PrimaryExpression ; 103 | 104 | Expression: Expression plus PrimaryExpression; 105 | /. 106 | case $rule_number: 107 | sym(1) += sym (3); 108 | break; 109 | ./ 110 | 111 | Expression: Expression minus PrimaryExpression; 112 | /. 113 | case $rule_number: 114 | sym(1) -= sym (3); 115 | break; 116 | ./ 117 | 118 | 119 | 120 | /. 121 | } // switch 122 | } 123 | 124 | #include 125 | 126 | int main() 127 | { 128 | CalcParser p; 129 | 130 | if (p.parse()) 131 | printf("ok\n"); 132 | } 133 | ./ 134 | -------------------------------------------------------------------------------- /doc/src/qlalr.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the documentation of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:FDL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Free Documentation License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Free 19 | ** Documentation License version 1.3 as published by the Free Software 20 | ** Foundation and appearing in the file included in the packaging of 21 | ** this file. Please review the following information to ensure 22 | ** the GNU Free Documentation License version 1.3 requirements 23 | ** will be met: http://www.gnu.org/copyleft/fdl.html. 24 | ** $QT_END_LICENSE$ 25 | ** 26 | ****************************************************************************/ 27 | 28 | /*! 29 | \page qlalr.html 30 | \title qlalr 31 | \nextpage qlalr - Writing Grammars 32 | 33 | \section1 Table of Contents 34 | 35 | \list 36 | \li \l{qlalr - Writing Grammars} 37 | \tableofcontents{1 qlalr - Writing Grammars} 38 | \li \l{qlalr - Generating Code from Grammar Specifications} 39 | \tableofcontents{1 qlalr - Generating Code from Grammar Specifications} 40 | \li \l{qlalr - qlalr Grammar Specification} 41 | \tableofcontents{1 qlalr - qlalr Grammar Specification} 42 | \li \l{qlalr - Handling Conflicts} 43 | \tableofcontents{1 qlalr - Handling Conflicts} 44 | \li \l{qlalr - Error Handling and Recovery} 45 | \tableofcontents{1 qlalr - Error Handling and Recovery} 46 | \li \l{qlalr - References to External Information} 47 | \tableofcontents{1 qlalr - References to External Information} 48 | \endlist 49 | 50 | */ 51 | 52 | /*! 53 | \page qlalr-files.html 54 | \title qlalr - Writing Grammars 55 | 56 | \contentspage qlalr 57 | \previouspage qlalr 58 | \nextpage qlalr - Generating Code from Grammar Specifications 59 | 60 | */ 61 | 62 | /*! 63 | \page qlalr-generating.html 64 | \title qlalr - Generating Code from Grammar Specifications 65 | 66 | \contentspage qlalr 67 | \previouspage qlalr - Writing Grammars 68 | \nextpage qlalr - qlalr Grammar Specification 69 | */ 70 | 71 | /*! 72 | \page qlalr-grammar-specification.html 73 | \title qlalr - qlalr Grammar Specification 74 | 75 | \contentspage qlalr 76 | \previouspage qlalr - Generating Code from Grammar Specifications 77 | \nextpage qlalr - Handling Conflicts 78 | 79 | */ 80 | 81 | /*! 82 | \page qlalr-handling-conflicts.html 83 | \title qlalr - Handling Conflicts 84 | 85 | \contentspage qlalr 86 | \previouspage qlalr - qlalr Grammar Specification 87 | \nextpage qlalr - Error Handling and Recovery 88 | */ 89 | 90 | /*! 91 | \page qlalr-handling-errors.html 92 | \title qlalr - Error Handling and Recovery 93 | 94 | \contentspage qlalr 95 | \previouspage qlalr - Handling Conflicts 96 | \nextpage qlalr - References to External Information 97 | */ 98 | 99 | /*! 100 | \page qlalr-external-references.html 101 | \title qlalr - References to External Information 102 | 103 | \contentspage qlalr 104 | \previouspage qlalr - Error Handling and Recovery 105 | */ 106 | 107 | -------------------------------------------------------------------------------- /src/recognizer.h: -------------------------------------------------------------------------------- 1 | 2 | /**************************************************************************** 3 | ** 4 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 5 | ** Contact: http://www.qt-project.org/legal 6 | ** 7 | ** This file is part of the QLALR project on Qt Labs. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and Digia. For licensing terms and 15 | ** conditions see http://qt.digia.com/licensing. For further information 16 | ** use the contact form at http://qt.digia.com/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 as published by the Free Software 21 | ** Foundation and appearing in the file LICENSE.LGPL included in the 22 | ** packaging of this file. Please review the following information to 23 | ** ensure the GNU Lesser General Public License version 2.1 requirements 24 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 | ** 26 | ** In addition, as a special exception, Digia gives you certain additional 27 | ** rights. These rights are described in the Digia Qt LGPL Exception 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 | ** 30 | ** GNU General Public License Usage 31 | ** Alternatively, this file may be used under the terms of the GNU 32 | ** General Public License version 3.0 as published by the Free Software 33 | ** Foundation and appearing in the file LICENSE.GPL included in the 34 | ** packaging of this file. Please review the following information to 35 | ** ensure the GNU General Public License version 3.0 requirements will be 36 | ** met: http://www.gnu.org/copyleft/gpl.html. 37 | ** 38 | ** 39 | ** $QT_END_LICENSE$ 40 | ** 41 | ****************************************************************************/ 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include "grammar_p.h" 49 | #include "lalr.h" 50 | 51 | #include 52 | 53 | class Recognizer: protected grammar 54 | { 55 | public: 56 | Recognizer (Grammar *grammar, bool no_lines); 57 | ~Recognizer(); 58 | 59 | bool parse (const QString &input_file = QString ()); 60 | 61 | inline QString decls () const { return _M_decls; } 62 | inline QString impls () const { return _M_impls; } 63 | 64 | protected: 65 | inline void reallocateStack (); 66 | 67 | inline QString &sym (int index) 68 | { return sym_stack [tos + index - 1]; } 69 | 70 | protected: // scanner 71 | int nextToken(); 72 | 73 | inline void inp () 74 | { 75 | if (_M_currentChar != _M_lastChar) 76 | { 77 | ch = *_M_currentChar++; 78 | 79 | if (ch == QLatin1Char('\n')) 80 | ++_M_line; 81 | } 82 | else 83 | ch = QChar(); 84 | } 85 | 86 | QString expand (const QString &text) const; 87 | 88 | protected: 89 | // recognizer 90 | int tos; 91 | int stack_size; 92 | QVector sym_stack; 93 | int *state_stack; 94 | 95 | QString _M_contents; 96 | QString::const_iterator _M_firstChar; 97 | QString::const_iterator _M_lastChar; 98 | QString::const_iterator _M_currentChar; 99 | 100 | // scanner 101 | QChar ch; 102 | int _M_line; 103 | int _M_action_line; 104 | Grammar *_M_grammar; 105 | RulePointer _M_current_rule; 106 | QString _M_input_file; 107 | 108 | QString _M_decls; 109 | QString _M_impls; 110 | QString _M_current_value; 111 | bool _M_no_lines; 112 | }; 113 | -------------------------------------------------------------------------------- /examples/dummy-xml/ll/dummy-xml-ll.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the QLALR module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #include 43 | #include 44 | 45 | enum Token { 46 | EOF_SYMBOL, 47 | LEFT_ANGLE, 48 | RIGHT_ANGLE, 49 | ANY, 50 | }; 51 | 52 | static int current_char; 53 | static int yytoken; 54 | static bool in_tag = false; 55 | 56 | bool parseXmlStream(); 57 | bool parseTagOrWord(); 58 | bool parseTagName(); 59 | 60 | inline int nextToken() 61 | { 62 | current_char = fgetc(stdin); 63 | if (current_char == EOF) { 64 | return (yytoken = EOF_SYMBOL); 65 | } else if (current_char == '<') { 66 | in_tag = true; 67 | return (yytoken = LEFT_ANGLE); 68 | } else if (in_tag && current_char == '>') { 69 | in_tag = false; 70 | return (yytoken = RIGHT_ANGLE); 71 | } 72 | return (yytoken = ANY); 73 | } 74 | 75 | bool parse() 76 | { 77 | nextToken(); 78 | return parseXmlStream(); 79 | } 80 | 81 | bool parseXmlStream() 82 | { 83 | while (parseTagOrWord()) 84 | ; 85 | 86 | return true; 87 | } 88 | 89 | bool parseTagOrWord() 90 | { 91 | if (yytoken == LEFT_ANGLE) { 92 | nextToken(); 93 | if (! parseTagName()) 94 | return false; 95 | if (yytoken != RIGHT_ANGLE) 96 | return false; 97 | nextToken(); 98 | 99 | fprintf (stderr, "*** found a tag\n"); 100 | 101 | } else if (yytoken == ANY) { 102 | nextToken(); 103 | } else { 104 | return false; 105 | } 106 | return true; 107 | } 108 | 109 | bool parseTagName() 110 | { 111 | while (yytoken == ANY) 112 | nextToken(); 113 | 114 | return true; 115 | } 116 | 117 | int main() 118 | { 119 | if (parse()) 120 | printf("OK\n"); 121 | else 122 | printf("KO\n"); 123 | } 124 | -------------------------------------------------------------------------------- /src/dotgraph.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | 43 | #include 44 | 45 | #include "lalr.h" 46 | #include "dotgraph.h" 47 | 48 | DotGraph::DotGraph(QTextStream &o): 49 | out (o) 50 | { 51 | } 52 | 53 | void DotGraph::operator () (Automaton *aut) 54 | { 55 | Grammar *g = aut->_M_grammar; 56 | 57 | out << "digraph {" << endl << endl; 58 | 59 | out << "subgraph Includes {" << endl; 60 | for (Automaton::IncludesGraph::iterator incl = Automaton::IncludesGraph::begin_nodes (); 61 | incl != Automaton::IncludesGraph::end_nodes (); ++incl) 62 | { 63 | for (Automaton::IncludesGraph::edge_iterator edge = incl->begin (); edge != incl->end (); ++edge) 64 | { 65 | out << "\t\"(" << aut->id (incl->data.state) << ", " << incl->data.nt << ")\""; 66 | out << "\t->\t"; 67 | out << "\"(" << aut->id ((*edge)->data.state) << ", " << (*edge)->data.nt << ")\"\t"; 68 | out << "[label=\"" << incl->data.state->follows [incl->data.nt] << "\"]"; 69 | out << endl; 70 | } 71 | } 72 | out << "}" << endl << endl; 73 | 74 | 75 | out << "subgraph LRA {" << endl; 76 | //out << "node [shape=record];" << endl << endl; 77 | 78 | for (StatePointer q = aut->states.begin (); q != aut->states.end (); ++q) 79 | { 80 | int state = aut->id (q); 81 | 82 | out << "\t" << state << "\t[shape=record,label=\"{"; 83 | 84 | out << "<0> State " << state; 85 | 86 | int index = 1; 87 | for (ItemPointer item = q->kernel.begin (); item != q->kernel.end (); ++item) 88 | out << "| <" << index++ << "> " << *item; 89 | 90 | out << "}\"]" << endl; 91 | 92 | for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) 93 | { 94 | const char *clr = g->isTerminal (a.key ()) ? "blue" : "red"; 95 | out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << endl; 96 | } 97 | out << endl; 98 | } 99 | 100 | out << "}" << endl; 101 | out << endl << endl << "}" << endl; 102 | } 103 | -------------------------------------------------------------------------------- /src/grammar_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | // 43 | // W A R N I N G 44 | // ------------- 45 | // 46 | // This file is not part of the Qt API. It exists for the convenience 47 | // of other Qt classes. This header file may change from version to 48 | // version without notice, or even be removed. 49 | // 50 | // We mean it. 51 | // 52 | 53 | // This file was generated by qlalr - DO NOT EDIT! 54 | #ifndef GRAMMAR_P_H 55 | #define GRAMMAR_P_H 56 | 57 | #include 58 | 59 | QT_BEGIN_NAMESPACE 60 | 61 | class grammar 62 | { 63 | public: 64 | enum VariousConstants { 65 | EOF_SYMBOL = 0, 66 | COLON = 16, 67 | DECL = 19, 68 | DECL_FILE = 3, 69 | ERROR = 21, 70 | EXPECT = 4, 71 | EXPECT_RR = 5, 72 | ID = 1, 73 | IMPL = 20, 74 | IMPL_FILE = 6, 75 | LEFT = 7, 76 | MERGED_OUTPUT = 8, 77 | NONASSOC = 9, 78 | OR = 17, 79 | PARSER = 10, 80 | PREC = 11, 81 | RIGHT = 12, 82 | SEMICOLON = 18, 83 | START = 13, 84 | STRING_LITERAL = 2, 85 | TOKEN = 14, 86 | TOKEN_PREFIX = 15, 87 | 88 | ACCEPT_STATE = 68, 89 | RULE_COUNT = 45, 90 | STATE_COUNT = 69, 91 | TERMINAL_COUNT = 22, 92 | NON_TERMINAL_COUNT = 24, 93 | 94 | GOTO_INDEX_OFFSET = 69, 95 | GOTO_INFO_OFFSET = 76, 96 | GOTO_CHECK_OFFSET = 76 97 | }; 98 | 99 | static const char *const spell []; 100 | static const short lhs []; 101 | static const short rhs []; 102 | static const short goto_default []; 103 | static const short action_default []; 104 | static const short action_index []; 105 | static const short action_info []; 106 | static const short action_check []; 107 | 108 | static inline int nt_action (int state, int nt) 109 | { 110 | const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; 111 | if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) 112 | return goto_default [nt]; 113 | 114 | return action_info [GOTO_INFO_OFFSET + yyn]; 115 | } 116 | 117 | static inline int t_action (int state, int token) 118 | { 119 | const int yyn = action_index [state] + token; 120 | 121 | if (yyn < 0 || action_check [yyn] != token) 122 | return - action_default [state]; 123 | 124 | return action_info [yyn]; 125 | } 126 | }; 127 | 128 | 129 | QT_END_NAMESPACE 130 | #endif // GRAMMAR_P_H 131 | 132 | -------------------------------------------------------------------------------- /doc/global/qt-module-defaults.qdocconf: -------------------------------------------------------------------------------- 1 | # 2 | # W A R N I N G 3 | # ------------- 4 | # 5 | # A common template for modules in this repository. 6 | # This template is common among the Qt 5 modules. 7 | # 8 | # A change in this template must be replicated in all of the repositories. 9 | # 10 | # We mean it. 11 | # 12 | 13 | codeindent = 1 14 | 15 | Cpp.ignoretokens = \ 16 | QDBUS_EXPORT \ 17 | QT_ASCII_CAST_WARN \ 18 | QT_ASCII_CAST_WARN_CONSTRUCTOR \ 19 | QT_BEGIN_HEADER \ 20 | QT_BEGIN_INCLUDE_NAMESPACE \ 21 | QT_BEGIN_NAMESPACE \ 22 | QT_BOOTSTRAPPED \ 23 | QT_DESIGNER_STATIC \ 24 | QT_END_HEADER \ 25 | QT_END_INCLUDE_NAMESPACE \ 26 | QT_END_NAMESPACE \ 27 | QT_FASTCALL \ 28 | Q_AUTOTEST_EXPORT \ 29 | Q_COMPAT_EXPORT \ 30 | Q_CORE_EXPORT \ 31 | Q_CORE_EXPORT_INLINE \ 32 | Q_DBUS_EXPORT \ 33 | Q_DECL_CONSTEXPR \ 34 | Q_DECL_NOEXCEPT \ 35 | Q_DECL_NOTHROW \ 36 | Q_EXPORT \ 37 | Q_EXPORT_PLUGIN \ 38 | Q_EXPORT_PLUGIN2 \ 39 | Q_GADGET \ 40 | Q_GUI_EXPORT \ 41 | Q_GUI_EXPORT_INLINE \ 42 | Q_INLINE_TEMPLATE \ 43 | Q_INVOKABLE \ 44 | Q_NETWORK_EXPORT \ 45 | Q_OPENGL_EXPORT \ 46 | Q_OPENVG_EXPORT \ 47 | Q_OUTOFLINE_TEMPLATE \ 48 | Q_PRINTSUPPORT_EXPORT \ 49 | Q_SQL_EXPORT \ 50 | Q_SVG_EXPORT \ 51 | Q_SCRIPT_EXPORT \ 52 | Q_SCRIPTTOOLS_EXPORT \ 53 | Q_WIDGETS_EXPORT \ 54 | Q_XML_EXPORT \ 55 | Q_XMLPATTERNS_EXPORT 56 | 57 | Cpp.ignoredirectives = \ 58 | __attribute__ \ 59 | QT_FORWARD_DECLARE_CLASS \ 60 | Q_CLASSINFO \ 61 | Q_DECLARE_INTERFACE \ 62 | Q_DECLARE_METATYPE \ 63 | Q_DECLARE_OPERATORS_FOR_FLAGS \ 64 | Q_DECLARE_PRIVATE \ 65 | Q_DECLARE_PUBLIC \ 66 | Q_DECLARE_PRIVATE_D \ 67 | Q_DECLARE_SHARED \ 68 | Q_DECLARE_TR_FUNCTIONS \ 69 | Q_DECLARE_TYPEINFO \ 70 | Q_DISABLE_COPY \ 71 | Q_DUMMY_COMPARISON_OPERATOR \ 72 | Q_ENUMS \ 73 | Q_FLAGS \ 74 | Q_INTERFACES \ 75 | Q_PRIVATE_PROPERTY 76 | 77 | defines = Q_QDOC \ 78 | QT_.*_SUPPORT \ 79 | QT_.*_LIB \ 80 | QT_COMPAT \ 81 | QT_KEYPAD_NAVIGATION \ 82 | QT_NO_EGL \ 83 | Q_OS_.* \ 84 | Q_BYTE_ORDER \ 85 | QT_DEPRECATED \ 86 | QT_DEPRECATED_* \ 87 | Q_NO_USING_KEYWORD \ 88 | __cplusplus \ 89 | Q_COMPILER_INITIALIZER_LISTS 90 | 91 | dita.metadata.default.author = Qt Project 92 | dita.metadata.default.permissions = all 93 | dita.metadata.default.publisher = Qt Project 94 | dita.metadata.default.copyryear = 2012 95 | dita.metadata.default.copyrholder = Nokia 96 | dita.metadata.default.audience = programmer 97 | 98 | naturallanguage = en_US 99 | outputencoding = UTF-8 100 | sourceencoding = UTF-8 101 | 102 | examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css" 103 | examples.imageextensions = "*.png *.jpg *.gif" 104 | 105 | headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" 106 | sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc" 107 | 108 | versionsym = QT_VERSION_STR 109 | 110 | -------------------------------------------------------------------------------- /src/parsetable.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | 43 | #include 44 | #include "lalr.h" 45 | #include "parsetable.h" 46 | 47 | ParseTable::ParseTable (QTextStream &o): 48 | out (o) 49 | { 50 | } 51 | 52 | void ParseTable::operator () (Automaton *aut) 53 | { 54 | Grammar *g = aut->_M_grammar; 55 | 56 | int rindex = 1; 57 | for (RulePointer rule = g->rules.begin (); rule != g->rules.end (); ++rule) 58 | out << rindex++ << ")\t" << *rule << endl; 59 | out << endl << endl; 60 | 61 | int index = 0; 62 | for (StatePointer state = aut->states.begin (); state != aut->states.end (); ++state) 63 | { 64 | out << "state " << index++ << endl << endl; 65 | 66 | for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item) 67 | { 68 | out << " * " << *item; 69 | 70 | if (item->dot == item->end_rhs ()) 71 | out << " " << aut->lookaheads [item]; 72 | 73 | out << endl; 74 | } 75 | 76 | bool first = true; 77 | for (Bundle::iterator arrow = state->bundle.begin (); arrow != state->bundle.end (); ++arrow) 78 | { 79 | if (! g->isTerminal (arrow.key ())) 80 | continue; 81 | 82 | if (first) 83 | out << endl; 84 | 85 | first = false; 86 | 87 | out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << endl; 88 | } 89 | 90 | first = true; 91 | for (ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item) 92 | { 93 | if (item->dot != item->end_rhs () || item->rule == state->defaultReduce) 94 | continue; 95 | 96 | if (first) 97 | out << endl; 98 | 99 | first = false; 100 | 101 | foreach (Name la, aut->lookaheads.value (item)) 102 | out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << endl; 103 | } 104 | 105 | first = true; 106 | for (Bundle::iterator arrow = state->bundle.begin (); arrow != state->bundle.end (); ++arrow) 107 | { 108 | if (! g->isNonTerminal (arrow.key ())) 109 | continue; 110 | 111 | if (first) 112 | out << endl; 113 | 114 | first = false; 115 | 116 | out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << endl; 117 | } 118 | 119 | if (state->defaultReduce != g->rules.end ()) 120 | { 121 | out << endl 122 | << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << endl; 123 | } 124 | 125 | out << endl; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /examples/qparser/qparser.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the QLALR module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef QPARSER_H 43 | #define QPARSER_H 44 | 45 | #include 46 | #include 47 | 48 | template 49 | class QParser: protected _Table 50 | { 51 | public: 52 | QParser(); 53 | ~QParser(); 54 | 55 | bool parse(); 56 | 57 | inline _Value &sym(int index); 58 | 59 | private: 60 | inline int nextToken() 61 | { 62 | return static_cast<_Parser*> (this)->nextToken(); 63 | } 64 | 65 | inline void consumeRule(int rule) 66 | { 67 | static_cast<_Parser*> (this)->consumeRule(rule); 68 | } 69 | 70 | enum { DefaultStackSize = 128 }; 71 | 72 | struct Data: public QSharedData 73 | { 74 | Data(): stackSize (DefaultStackSize), tos (0) {} 75 | 76 | QVarLengthArray stateStack; 77 | QVarLengthArray<_Value, DefaultStackSize> parseStack; 78 | int stackSize; 79 | int tos; 80 | 81 | void reallocateStack() { 82 | stackSize <<= 1; 83 | stateStack.resize(stackSize); 84 | parseStack.resize(stackSize); 85 | } 86 | }; 87 | 88 | QSharedDataPointer d; 89 | }; 90 | 91 | template 92 | inline _Value &QParser<_Parser, _Table, _Value>::sym(int n) 93 | { 94 | return d->parseStack [d->tos + n - 1]; 95 | } 96 | 97 | template 98 | QParser<_Parser, _Table, _Value>::QParser(): 99 | d(new Data()) 100 | { 101 | } 102 | 103 | template 104 | QParser<_Parser, _Table, _Value>::~QParser() 105 | { 106 | } 107 | 108 | template 109 | bool QParser<_Parser, _Table, _Value>::parse() 110 | { 111 | const int INITIAL_STATE = 0; 112 | 113 | d->tos = 0; 114 | d->reallocateStack(); 115 | 116 | int act = d->stateStack[++d->tos] = INITIAL_STATE; 117 | int token = -1; 118 | 119 | forever { 120 | if (token == -1 && - _Table::TERMINAL_COUNT != _Table::action_index[act]) 121 | token = nextToken(); 122 | 123 | act = _Table::t_action(act, token); 124 | 125 | if (d->stateStack[d->tos] == _Table::ACCEPT_STATE) 126 | return true; 127 | 128 | else if (act > 0) { 129 | if (++d->tos == d->stackSize) 130 | d->reallocateStack(); 131 | 132 | d->parseStack[d->tos] = d->parseStack[d->tos - 1]; 133 | d->stateStack[d->tos] = act; 134 | token = -1; 135 | } 136 | 137 | else if (act < 0) { 138 | int r = - act - 1; 139 | d->tos -= _Table::rhs[r]; 140 | act = d->stateStack[d->tos++]; 141 | consumeRule(r); 142 | act = d->stateStack[d->tos] = _Table::nt_action(act, _Table::lhs[r] - _Table::TERMINAL_COUNT); 143 | } 144 | 145 | else break; 146 | } 147 | 148 | return false; 149 | } 150 | 151 | 152 | #endif // QPARSER_H 153 | -------------------------------------------------------------------------------- /src/grammar.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | // This file was generated by qlalr - DO NOT EDIT! 43 | #include "grammar_p.h" 44 | 45 | QT_BEGIN_NAMESPACE 46 | 47 | const char *const grammar::spell [] = { 48 | "end of file", "identifier", "string literal", "%decl", "%expect", "%expect-lr", "%impl", "%left", "%merged_output", "%nonassoc", 49 | "%parser", "%prec", "%right", "%start", "%token", "%token_prefix", ":", "|", ";", 0, 50 | 0, 0}; 51 | 52 | const short grammar::lhs [] = { 53 | 22, 23, 23, 29, 25, 28, 28, 28, 28, 28, 54 | 28, 28, 24, 24, 31, 32, 32, 33, 33, 34, 55 | 34, 34, 31, 35, 35, 36, 37, 37, 38, 38, 56 | 30, 30, 26, 26, 40, 39, 41, 41, 44, 43, 57 | 43, 42, 42, 27, 45}; 58 | 59 | const short grammar::rhs [] = { 60 | 4, 1, 2, 2, 2, 2, 2, 2, 2, 2, 61 | 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 62 | 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 63 | 0, 1, 1, 2, 2, 4, 3, 6, 0, 0, 64 | 2, 1, 2, 0, 2}; 65 | 66 | const short grammar::action_default [] = { 67 | 44, 2, 44, 0, 0, 0, 0, 13, 0, 0, 68 | 3, 0, 0, 0, 8, 10, 11, 9, 7, 6, 69 | 12, 20, 22, 0, 21, 0, 44, 31, 0, 14, 70 | 26, 24, 23, 25, 4, 33, 1, 0, 34, 44, 71 | 35, 42, 39, 40, 0, 31, 44, 40, 43, 0, 72 | 31, 41, 29, 27, 28, 32, 38, 30, 36, 31, 73 | 37, 5, 44, 16, 15, 18, 19, 17, 45}; 74 | 75 | const short grammar::goto_default [] = { 76 | 3, 2, 13, 26, 36, 41, 10, 27, 61, 29, 77 | 64, 63, 23, 32, 31, 52, 55, 38, 39, 42, 78 | 43, 59, 44, 0}; 79 | 80 | const short grammar::action_index [] = { 81 | -22, -22, 54, 1, 5, 15, 20, -22, -1, 6, 82 | -22, 3, 2, 35, -22, -22, -22, -22, -22, -22, 83 | -22, -22, -22, 10, -22, 7, -22, 14, 9, -22, 84 | -22, -22, 8, -22, -22, -22, 11, -2, -22, -22, 85 | -22, -22, -3, 16, 13, 14, -22, 17, -22, 4, 86 | 14, -22, -22, -22, -22, 14, -22, -22, -22, 14, 87 | -22, -22, 0, -22, 12, -22, -22, -22, -22, 88 | 89 | 2, -24, -2, -24, -24, -24, -24, -24, -24, -24, 90 | -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, 91 | -24, -24, -24, -24, -24, -24, -4, -24, -24, -24, 92 | -24, -24, -14, -24, -24, -24, -24, -24, -24, -24, 93 | -24, -24, -24, -24, -24, 0, -16, -15, -24, -24, 94 | 15, -24, -24, -24, -24, -10, -24, -24, -24, 1, 95 | -24, -24, -3, -24, -1, -24, -24, -24, -24}; 96 | 97 | const short grammar::action_info [] = { 98 | 17, 68, 66, 20, 19, 51, 14, 18, 34, 30, 99 | 62, 30, 37, 62, 40, 45, 15, 48, 48, 0, 100 | 0, 16, 0, 0, 0, 0, 0, 49, 49, 0, 101 | 46, 0, 0, 53, 54, 0, 0, 0, 0, 0, 102 | 0, 0, 21, 0, 22, 0, 0, 24, 25, 28, 103 | 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 104 | 8, 0, 9, 0, 11, 0, 0, 0, 0, 12, 105 | 0, 0, 0, 0, 0, 0, 106 | 107 | 33, 35, 65, 7, 47, 57, 50, 1, 58, 60, 108 | 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109 | 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 110 | 0, 0, 0, 0, 0, 0, 0, 0, 0}; 111 | 112 | const short grammar::action_check [] = { 113 | 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 114 | 1, 1, 1, 1, 16, 18, 1, 1, 1, -1, 115 | -1, 1, -1, -1, -1, -1, -1, 11, 11, -1, 116 | 17, -1, -1, 19, 20, -1, -1, -1, -1, -1, 117 | -1, -1, 7, -1, 9, -1, -1, 12, 13, 14, 118 | -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 119 | 6, -1, 8, -1, 10, -1, -1, -1, -1, 15, 120 | -1, -1, -1, -1, -1, -1, 121 | 122 | 14, 5, 5, 5, 20, 15, 21, 5, 8, 8, 123 | 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, 124 | -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, 125 | -1, -1, -1, -1, -1, -1, -1, -1, -1}; 126 | 127 | QT_END_NAMESPACE 128 | -------------------------------------------------------------------------------- /examples/lambda/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the QLALR module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #include "lambda.h" 43 | 44 | #include 45 | #include 46 | #include 47 | #include "parser_table_p.h" 48 | 49 | class Parser: protected parser_table 50 | { 51 | public: 52 | union Value { 53 | int ival; 54 | // ### more... 55 | }; 56 | 57 | public: 58 | Parser(); 59 | ~Parser(); 60 | 61 | bool parse(); 62 | 63 | protected: 64 | inline void reallocateStack(); 65 | 66 | inline Value &sym(int index) 67 | { return sym_stack [tos + index - 1]; } 68 | 69 | int nextToken(); 70 | void consumeRule(int ruleno); 71 | 72 | protected: 73 | int tos; 74 | int stack_size; 75 | Value *sym_stack; 76 | int *state_stack; 77 | int current_char; 78 | unsigned in_tag: 1; 79 | }; 80 | 81 | inline void Parser::reallocateStack() 82 | { 83 | if (! stack_size) 84 | stack_size = 128; 85 | else 86 | stack_size <<= 1; 87 | 88 | sym_stack = reinterpret_cast (::realloc(sym_stack, stack_size * sizeof(Value))); 89 | state_stack = reinterpret_cast (::realloc(state_stack, stack_size * sizeof(int))); 90 | } 91 | 92 | Parser::Parser(): 93 | tos(0), 94 | stack_size(0), 95 | sym_stack(0), 96 | state_stack(0) 97 | { 98 | } 99 | 100 | Parser::~Parser() 101 | { 102 | if (stack_size) { 103 | ::free(sym_stack); 104 | ::free(state_stack); 105 | } 106 | } 107 | 108 | bool Parser::parse() 109 | { 110 | const int INITIAL_STATE = 0; 111 | 112 | current_char = 0; 113 | in_tag = 0; 114 | 115 | int yytoken = -1; 116 | reallocateStack(); 117 | 118 | tos = 0; 119 | state_stack[++tos] = INITIAL_STATE; 120 | 121 | while (true) 122 | { 123 | if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]]) 124 | yytoken = nextToken(); 125 | 126 | int act = t_action (state_stack [tos], yytoken); 127 | 128 | if (act == ACCEPT_STATE) { 129 | return true; 130 | } 131 | 132 | else if (act > 0) 133 | { 134 | if (++tos == stack_size) 135 | reallocateStack(); 136 | 137 | sym_stack [tos].ival = current_char; // ### save the token value here 138 | state_stack [tos] = act; 139 | yytoken = -1; 140 | } 141 | 142 | else if (act < 0) 143 | { 144 | int r = - act - 1; 145 | 146 | tos -= rhs [r]; 147 | act = state_stack [tos++]; 148 | consumeRule (r); 149 | state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT); 150 | } 151 | 152 | else 153 | break; 154 | } 155 | 156 | return false; 157 | } 158 | 159 | 160 | int Parser::nextToken() 161 | { 162 | static int tokens[] = { ID, ID, ID, EOF_SYMBOL }; 163 | static int *tk = tokens; 164 | 165 | return *tk++; 166 | } 167 | 168 | void Parser::consumeRule(int ruleno) 169 | { 170 | switch (ruleno) { 171 | case Symbol: 172 | printf("symbol\n"); 173 | break; 174 | case SubExpression: 175 | printf("sub-expr\n"); 176 | break; 177 | case Appl: 178 | printf("appl\n"); 179 | break; 180 | case Abstr: 181 | printf("abstr\n"); 182 | break; 183 | } 184 | } 185 | 186 | ///////////////////////////// 187 | // entry point 188 | ///////////////////////////// 189 | int main() 190 | { 191 | Parser parser; 192 | 193 | if (parser.parse()) 194 | printf ("OK\n"); 195 | else 196 | printf ("KO\n"); 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /examples/dummy-xml/xml.g: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- 3 | -- Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | -- Contact: http://www.qt-project.org/legal 5 | -- 6 | -- This file is part of the QtCore module of the Qt Toolkit. 7 | -- 8 | -- $QT_BEGIN_LICENSE:LGPL$ 9 | -- Commercial License Usage 10 | -- Licensees holding valid commercial Qt licenses may use this file in 11 | -- accordance with the commercial license agreement provided with the 12 | -- Software or, alternatively, in accordance with the terms contained in 13 | -- a written agreement between you and Digia. For licensing terms and 14 | -- conditions see http://qt.digia.com/licensing. For further information 15 | -- use the contact form at http://qt.digia.com/contact-us. 16 | -- 17 | -- GNU Lesser General Public License Usage 18 | -- Alternatively, this file may be used under the terms of the GNU Lesser 19 | -- General Public License version 2.1 as published by the Free Software 20 | -- Foundation and appearing in the file LICENSE.LGPL included in the 21 | -- packaging of this file. Please review the following information to 22 | -- ensure the GNU Lesser General Public License version 2.1 requirements 23 | -- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | -- 25 | -- In addition, as a special exception, Digia gives you certain additional 26 | -- rights. These rights are described in the Digia Qt LGPL Exception 27 | -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | -- 29 | -- GNU General Public License Usage 30 | -- Alternatively, this file may be used under the terms of the GNU 31 | -- General Public License version 3.0 as published by the Free Software 32 | -- Foundation and appearing in the file LICENSE.GPL included in the 33 | -- packaging of this file. Please review the following information to 34 | -- ensure the GNU General Public License version 3.0 requirements will be 35 | -- met: http://www.gnu.org/copyleft/gpl.html. 36 | -- 37 | -- 38 | -- $QT_END_LICENSE$ 39 | -- 40 | ---------------------------------------------------------------------------- 41 | 42 | %parser XMLTable 43 | 44 | %impl xmlreader.cpp 45 | 46 | %token LEFT_ANGLE 47 | %token RIGHT_ANGLE 48 | %token ANY 49 | 50 | %start XmlStream 51 | 52 | /. 53 | #ifndef XMLREADER_H 54 | #define XMLREADER_H 55 | 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include "$header" 61 | 62 | class XMLReader: protected $table 63 | { 64 | public: 65 | XMLReader(const QByteArray &bytes); 66 | ~XMLReader(); 67 | 68 | bool parse(); 69 | 70 | inline int nextToken() 71 | { 72 | switch (*bufptr++) { 73 | case '\0': 74 | return EOF_SYMBOL; 75 | 76 | case '<': 77 | in_tag = true; 78 | return LEFT_ANGLE; 79 | 80 | case '>': 81 | if (! in_tag) 82 | break; 83 | in_tag = false; 84 | return RIGHT_ANGLE; 85 | break; 86 | 87 | } // switch 88 | 89 | return ANY; 90 | } 91 | 92 | protected: 93 | inline void reallocateStack(); 94 | 95 | inline int &sym(int index) 96 | { return stack [tos + index - 1].ival; } 97 | 98 | protected: 99 | int tos; 100 | int stack_size; 101 | 102 | struct StackItem { 103 | int state; 104 | int ival; 105 | }; 106 | 107 | QVarLengthArray stack; 108 | unsigned in_tag: 1; 109 | QByteArray bytes; 110 | const char *bufptr; 111 | }; 112 | 113 | inline void XMLReader::reallocateStack() 114 | { 115 | if (! stack_size) 116 | stack_size = 128; 117 | else 118 | stack_size <<= 1; 119 | 120 | stack.resize (stack_size); 121 | } 122 | 123 | #endif // XMLREADER_H 124 | 125 | XMLReader::XMLReader(const QByteArray &bytes): 126 | tos(0), 127 | stack_size(0), 128 | bytes(bytes) 129 | { 130 | bufptr = bytes.constData(); 131 | } 132 | 133 | XMLReader::~XMLReader() 134 | { 135 | } 136 | 137 | bool XMLReader::parse() 138 | { 139 | const int INITIAL_STATE = 0; 140 | 141 | in_tag = 0; 142 | bufptr = bytes.constData(); 143 | 144 | int yytoken = -1; 145 | reallocateStack(); 146 | 147 | tos = 0; 148 | stack [++tos].state = INITIAL_STATE; 149 | 150 | while (true) 151 | { 152 | const int state = stack [tos].state; 153 | 154 | if (yytoken == -1 && - TERMINAL_COUNT != action_index [state]) 155 | yytoken = nextToken(); 156 | 157 | int act = t_action (state, yytoken); 158 | 159 | if (act == ACCEPT_STATE) 160 | return true; 161 | 162 | else if (act > 0) 163 | { 164 | if (++tos == stack_size) 165 | reallocateStack(); 166 | 167 | stack [tos].ival = *bufptr; // ### save the token value here 168 | stack [tos].state = act; 169 | yytoken = -1; 170 | } 171 | 172 | else if (act < 0) 173 | { 174 | int r = - act - 1; 175 | 176 | tos -= rhs [r]; 177 | act = stack [tos++].state; 178 | 179 | switch (r) { 180 | ./ 181 | 182 | 183 | 184 | 185 | XmlStream: TagOrWord ; 186 | XmlStream: XmlStream TagOrWord ; 187 | 188 | TagOrWord: Tag ; 189 | TagOrWord: ANY ; 190 | 191 | Tag: LEFT_ANGLE TagName RIGHT_ANGLE ; 192 | /. 193 | case $rule_number: { 194 | fprintf (stderr, "*** found a tag\n"); 195 | } break; 196 | ./ 197 | 198 | TagName: ANY ; 199 | TagName: TagName ANY ; 200 | 201 | 202 | /. 203 | } // switch 204 | 205 | stack [tos].state = nt_action (act, lhs [r] - TERMINAL_COUNT); 206 | } 207 | 208 | else 209 | { 210 | // ### ERROR RECOVERY HERE 211 | break; 212 | } 213 | } 214 | 215 | return false; 216 | } 217 | 218 | 219 | 220 | ///////////////////////////// 221 | // entry point 222 | ///////////////////////////// 223 | int main(int, char *argv[]) 224 | { 225 | QFile f (argv[1]); 226 | 227 | if (f.open(QFile::ReadOnly)) { 228 | QByteArray contents = f.readAll(); 229 | XMLReader parser (contents); 230 | 231 | if (parser.parse()) 232 | printf ("OK\n"); 233 | else 234 | printf ("KO\n"); 235 | } 236 | } 237 | 238 | 239 | 240 | 241 | ./ 242 | 243 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include 48 | 49 | #include "lalr.h" 50 | #include "dotgraph.h" 51 | #include "parsetable.h" 52 | #include "cppgenerator.h" 53 | #include "recognizer.h" 54 | 55 | #define QLALR_NO_DEBUG_TABLE 56 | #define QLALR_NO_DEBUG_DOT 57 | 58 | static void help_me () 59 | { 60 | qerr << "Usage: qlalr [options] [input file name]" << endl 61 | << endl 62 | << " --help, -h\t\tdisplay this help and exit" << endl 63 | << " --verbose, -v\t\tverbose output" << endl 64 | << " --no-debug\t\tno debug information" << endl 65 | << " --no-lines\t\tno #line directives" << endl 66 | << " --dot\t\t\tgenerate a graph" << endl 67 | << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << endl 68 | << endl; 69 | exit (0); 70 | } 71 | 72 | int main (int argc, char *argv[]) 73 | { 74 | QCoreApplication app (argc, argv); 75 | 76 | bool generate_dot = false; 77 | bool generate_report = false; 78 | bool no_lines = false; 79 | bool debug_info = true; 80 | bool qt_copyright = false; 81 | QString file_name = 0; 82 | 83 | QStringList args = app.arguments (); 84 | args.removeFirst (); 85 | 86 | foreach (QString arg, args) 87 | { 88 | if (arg == QLatin1String ("-h") || arg == QLatin1String ("--help")) 89 | help_me (); 90 | 91 | else if (arg == QLatin1String ("-v") || arg == QLatin1String ("--verbose")) 92 | generate_report = true; 93 | 94 | else if (arg == QLatin1String ("--dot")) 95 | generate_dot = true; 96 | 97 | else if (arg == QLatin1String ("--no-lines")) 98 | no_lines = true; 99 | 100 | else if (arg == QLatin1String ("--no-debug")) 101 | debug_info = false; 102 | 103 | else if (arg == QLatin1String ("--qt")) 104 | qt_copyright = true; 105 | 106 | else if (file_name.isEmpty ()) 107 | file_name = arg; 108 | 109 | else 110 | qerr << "*** Warning. Ignore argument `" << arg << "'" << endl; 111 | } 112 | 113 | if (file_name.isEmpty ()) 114 | { 115 | help_me (); 116 | exit (EXIT_SUCCESS); 117 | } 118 | 119 | Grammar grammar; 120 | Recognizer p (&grammar, no_lines); 121 | 122 | if (! p.parse (file_name)) 123 | exit (EXIT_FAILURE); 124 | 125 | if (grammar.rules.isEmpty ()) 126 | { 127 | qerr << "*** Fatal. No rules!" << endl; 128 | exit (EXIT_FAILURE); 129 | } 130 | 131 | else if (grammar.start == grammar.names.end ()) 132 | { 133 | qerr << "*** Fatal. No start symbol!" << endl; 134 | exit (EXIT_FAILURE); 135 | } 136 | 137 | grammar.buildExtendedGrammar (); 138 | grammar.buildRuleMap (); 139 | 140 | Automaton aut (&grammar); 141 | aut.build (); 142 | 143 | CppGenerator gen (p, grammar, aut, generate_report); 144 | gen.setDebugInfo (debug_info); 145 | gen.setCopyright (qt_copyright); 146 | gen (); 147 | 148 | if (generate_dot) 149 | { 150 | DotGraph genDotFile (qout); 151 | genDotFile (&aut); 152 | } 153 | 154 | else if (generate_report) 155 | { 156 | ParseTable genParseTable (qout); 157 | genParseTable(&aut); 158 | } 159 | 160 | return EXIT_SUCCESS; 161 | } 162 | 163 | QString Recognizer::expand (const QString &text) const 164 | { 165 | QString code = text; 166 | 167 | if (_M_grammar->start != _M_grammar->names.end ()) 168 | { 169 | code = code.replace (QLatin1String("$start_id"), QString::number (std::distance (_M_grammar->names.begin (), _M_grammar->start))); 170 | code = code.replace (QLatin1String("$start"), *_M_grammar->start); 171 | } 172 | 173 | code = code.replace (QLatin1String("$header"), _M_grammar->table_name.toLower () + QLatin1String("_p.h")); 174 | 175 | code = code.replace (QLatin1String("$table"), _M_grammar->table_name); 176 | code = code.replace (QLatin1String("$parser"), _M_grammar->table_name); 177 | 178 | if (_M_current_rule != _M_grammar->rules.end ()) 179 | { 180 | code = code.replace (QLatin1String("$rule_number"), QString::number (std::distance (_M_grammar->rules.begin (), _M_current_rule))); 181 | code = code.replace (QLatin1String("$rule"), *_M_current_rule->lhs); 182 | } 183 | 184 | return code; 185 | } 186 | -------------------------------------------------------------------------------- /examples/glsl/glsl-lex.l: -------------------------------------------------------------------------------- 1 | 2 | %{ 3 | /**************************************************************************** 4 | ** 5 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 6 | ** Contact: http://www.qt-project.org/legal 7 | ** 8 | ** This file is part of the QLALR tool of the Qt Toolkit. 9 | ** 10 | ** $QT_BEGIN_LICENSE:LGPL$ 11 | ** Commercial License Usage 12 | ** Licensees holding valid commercial Qt licenses may use this file in 13 | ** accordance with the commercial license agreement provided with the 14 | ** Software or, alternatively, in accordance with the terms contained in 15 | ** a written agreement between you and Digia. For licensing terms and 16 | ** conditions see http://qt.digia.com/licensing. For further information 17 | ** use the contact form at http://qt.digia.com/contact-us. 18 | ** 19 | ** GNU Lesser General Public License Usage 20 | ** Alternatively, this file may be used under the terms of the GNU Lesser 21 | ** General Public License version 2.1 as published by the Free Software 22 | ** Foundation and appearing in the file LICENSE.LGPL included in the 23 | ** packaging of this file. Please review the following information to 24 | ** ensure the GNU Lesser General Public License version 2.1 requirements 25 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 26 | ** 27 | ** In addition, as a special exception, Digia gives you certain additional 28 | ** rights. These rights are described in the Digia Qt LGPL Exception 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 30 | ** 31 | ** GNU General Public License Usage 32 | ** Alternatively, this file may be used under the terms of the GNU 33 | ** General Public License version 3.0 as published by the Free Software 34 | ** Foundation and appearing in the file LICENSE.GPL included in the 35 | ** packaging of this file. Please review the following information to 36 | ** ensure the GNU General Public License version 3.0 requirements will be 37 | ** met: http://www.gnu.org/copyleft/gpl.html. 38 | ** 39 | ** 40 | ** $QT_END_LICENSE$ 41 | ** 42 | ****************************************************************************/ 43 | 44 | #include 45 | #define YY_DECL int GLSLParser::nextToken() 46 | %} 47 | 48 | %option noyywrap 49 | 50 | hex [0-9a-fA-F] 51 | dec [1-9][0-9]* 52 | oct [0-7] 53 | digit [0-9] 54 | 55 | fract {digit}*\.{digit}+|{digit}+\. 56 | exp [eE][+-]?{digit}+ 57 | 58 | hexfract {hex}*\.{hex}+|{hex}+\. 59 | binexp [pP][+-]?{digit}+ 60 | 61 | icst ({dec}|0{oct}*|0[xX]{hex}+) 62 | 63 | %% 64 | 65 | [\n] { ++context.line; } 66 | [ \t\r]+ { /* skip */ } 67 | 68 | "+=" { return ADD_ASSIGN; } 69 | "&" { return AMPERSAND; } 70 | "&=" { return AND_ASSIGN; } 71 | "&&" { return AND_OP; } 72 | "attribute" { return ATTRIBUTE; } 73 | "!" { return BANG; } 74 | "bool" { return BOOL; } 75 | "true" { return BOOLCONSTANT; } 76 | "false" { return BOOLCONSTANT; } 77 | "break" { return BREAK; } 78 | "bvec2" { return BVEC2; } 79 | "bvec3" { return BVEC3; } 80 | "bvec4" { return BVEC4; } 81 | ":" { return COLON; } 82 | "," { return COMMA; } 83 | "const" { return CONST; } 84 | "continue" { return CONTINUE; } 85 | "-" { return DASH; } 86 | "--" { return DEC_OP; } 87 | "discard" { return DISCARD; } 88 | "/=" { return DIV_ASSIGN; } 89 | "do" { return DO; } 90 | "." { return DOT; } 91 | "else" { return ELSE; } 92 | "=" { return EQUAL; } 93 | "==" { return EQ_OP; } 94 | "float" { return FLOAT; } 95 | "for" { return FOR; } 96 | ">=" { return GE_OP; } 97 | "if" { return IF; } 98 | "in" { return IN; } 99 | "++" { return INC_OP; } 100 | "inout" { return INOUT; } 101 | "int" { return INT; } 102 | "ivec2" { return IVEC2; } 103 | "ivec3" { return IVEC3; } 104 | "ivec4" { return IVEC4; } 105 | "<" { return LEFT_ANGLE; } 106 | "<<=" { return LEFT_ASSIGN; } 107 | "{" { return LEFT_BRACE; } 108 | "[" { return LEFT_BRACKET; } 109 | "<<" { return LEFT_OP; } 110 | "(" { return LEFT_PAREN; } 111 | "<=" { return LE_OP; } 112 | "mat2" { return MAT2; } 113 | "mat3" { return MAT3; } 114 | "mat4" { return MAT4; } 115 | "%=" { return MOD_ASSIGN; } 116 | "*=" { return MUL_ASSIGN; } 117 | "!=" { return NE_OP; } 118 | "|=" { return OR_ASSIGN; } 119 | "||" { return OR_OP; } 120 | "out" { return OUT; } 121 | "%" { return PERCENT; } 122 | "+" { return PLUS; } 123 | "?" { return QUESTION; } 124 | "return" { return RETURN; } 125 | ">" { return RIGHT_ANGLE; } 126 | ">>=" { return RIGHT_ASSIGN; } 127 | "}" { return RIGHT_BRACE; } 128 | "]" { return RIGHT_BRACKET; } 129 | ">>" { return RIGHT_OP; } 130 | ")" { return RIGHT_PAREN; } 131 | "sampler1D" { return SAMPLER1D; } 132 | "sampler1DShadow" { return SAMPLER1DSHADOW; } 133 | "sampler2D" { return SAMPLER2D; } 134 | "sampler2DShadow" { return SAMPLER2DSHADOW; } 135 | "sampler3D" { return SAMPLER3D; } 136 | "samplerCube" { return SAMPLERCUBE; } 137 | ";" { return SEMICOLON; } 138 | "/" { return SLASH; } 139 | "*" { return STAR; } 140 | "struct" { return STRUCT; } 141 | "-=" { return SUB_ASSIGN; } 142 | "~" { return TILDE; } 143 | "uniform" { return UNIFORM; } 144 | "varying" { return VARYING; } 145 | "vec2" { return VEC2; } 146 | "vec3" { return VEC3; } 147 | "vec4" { return VEC4; } 148 | "|" { return VERTICAL_BAR; } 149 | "void" { return VOID; } 150 | "while" { return WHILE; } 151 | "^=" { return XOR_ASSIGN; } 152 | "^" { return XOR_OP; } 153 | "highp" { return HIGH_PRECISION; } 154 | "mediump" { return MEDIUM_PRECISION; } 155 | "lowp" { return LOW_PRECISION; } 156 | 157 | #[ \t]+[0-9]+.* { 158 | char *eptr = 0; 159 | context.line = (int) strtod(&yytext[1], &eptr); 160 | QString fn = QString::fromUtf8(eptr).trimmed(); 161 | if (fn.length() > 2) 162 | context.fileName = fn.mid(1, fn.length()-2); 163 | } 164 | 165 | #.* { 166 | /* skip */ 167 | } 168 | 169 | [_a-zA-Z][_a-zA-Z0-9]* { 170 | yylval.s = intern (yytext); 171 | 172 | if (isTypename (yylval.s)) 173 | return TYPE_NAME; 174 | 175 | return IDENTIFIER; 176 | } 177 | 178 | {icst} { 179 | yylval.i = (int) strtol (yytext, 0, 0); 180 | return INTCONSTANT; 181 | } 182 | 183 | {icst}[uU] { 184 | yylval.u = (unsigned) strtoul (yytext, 0, 0); 185 | return INTCONSTANT; 186 | } 187 | 188 | {icst}[uU][lL] { 189 | yylval.ul = strtoul (yytext, 0, 0); 190 | return INTCONSTANT; 191 | } 192 | 193 | {icst}[lL][uU] { 194 | yylval.ul = strtoul (yytext, 0, 0); 195 | return INTCONSTANT; 196 | } 197 | 198 | {icst}[lL] { 199 | yylval.l = strtol (yytext, 0, 0); 200 | return INTCONSTANT; 201 | } 202 | 203 | {icst}[uU](ll|LL) { 204 | yylval.l = strtoull (yytext, 0, 0); 205 | return INTCONSTANT; 206 | } 207 | 208 | {icst}(ll|LL) { 209 | yylval.l = strtoll (yytext, 0, 0); 210 | return INTCONSTANT; 211 | } 212 | 213 | {icst}(ll|LL)[uU] { 214 | yylval.l = strtoull (yytext, 0, 0); 215 | return INTCONSTANT; 216 | } 217 | 218 | {fract}{exp}?[flFL]? { 219 | yylval.f = strtof (yytext, 0); 220 | return FLOATCONSTANT; 221 | } 222 | 223 | {digit}+{exp}[flFL]? { 224 | yylval.f = strtof (yytext, 0); 225 | return FLOATCONSTANT; 226 | } 227 | 228 | 0[xX]{hexfract}{binexp}[flFL]? { 229 | yylval.f = strtof (yytext, 0); 230 | return FLOATCONSTANT; 231 | } 232 | 233 | 0[xX]{hex}+{binexp}[flFL]? { 234 | yylval.f = strtof (yytext, 0); 235 | return FLOATCONSTANT; 236 | } 237 | 238 | . { 239 | fprintf (stderr, "invalid char: %d\n", yytext [0]); 240 | return ERROR; 241 | } 242 | 243 | 244 | %% 245 | 246 | -------------------------------------------------------------------------------- /src/compress.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the test suite module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include "compress.h" 50 | 51 | #define QLALR_NO_CHECK_SORTED_TABLE 52 | 53 | struct _Fit: public std::binary_function 54 | { 55 | inline bool operator () (int a, int b) const 56 | { 57 | return a == 0 || b == 0 || a == b; 58 | } 59 | }; 60 | 61 | struct _PerfectMatch: public std::binary_function 62 | { 63 | inline bool operator () (int a, int b) const 64 | { return a == b; } 65 | }; 66 | 67 | struct _GenerateCheck 68 | { 69 | QVector::const_iterator iterator; 70 | int initial; 71 | 72 | _GenerateCheck (QVector::const_iterator it, int i): 73 | iterator (it), 74 | initial (i) {} 75 | 76 | inline int operator () () 77 | { 78 | int check = initial++; 79 | return *iterator++ ? check : -1; 80 | } 81 | }; 82 | 83 | class UncompressedRow 84 | { 85 | public: 86 | typedef const int *const_iterator; 87 | typedef const int *iterator; 88 | 89 | public: 90 | inline UncompressedRow (): 91 | _M_index (0), 92 | _M_begin (0), 93 | _M_end (0), 94 | _M_beginNonZeros (0), 95 | _M_endNonZeros (0) {} 96 | 97 | inline UncompressedRow (int index, const_iterator begin, const_iterator end) 98 | { assign (index, begin, end); } 99 | 100 | inline int index () const { return _M_index; } 101 | inline const_iterator begin () const { return _M_begin; } 102 | inline const_iterator end () const { return _M_end; } 103 | 104 | inline void assign (int index, const_iterator begin, const_iterator end) 105 | { 106 | _M_index = index; 107 | _M_begin = begin; 108 | _M_end = end; 109 | 110 | _M_beginNonZeros = _M_begin; 111 | _M_endNonZeros = _M_end; 112 | 113 | for (_M_beginNonZeros = _M_begin; _M_beginNonZeros != _M_end && ! _M_beginNonZeros [0]; ++_M_beginNonZeros) 114 | /*continue*/ ; 115 | 116 | #if 0 117 | for (_M_endNonZeros = _M_end; _M_endNonZeros != _M_beginNonZeros && ! _M_endNonZeros [-1]; --_M_endNonZeros) 118 | /*continue*/ ; 119 | #endif 120 | } 121 | 122 | inline int at (int index) const 123 | { return _M_begin [index]; } 124 | 125 | inline bool isEmpty () const 126 | { return _M_begin == _M_end; } 127 | 128 | inline int size () const 129 | { return _M_end - _M_begin; } 130 | 131 | inline int nonZeroElements () const 132 | { return _M_endNonZeros - _M_beginNonZeros; } 133 | 134 | inline int count (int value) const 135 | { return std::count (begin (), end (), value); } 136 | 137 | inline const_iterator beginNonZeros () const 138 | { return _M_beginNonZeros; } 139 | 140 | inline const_iterator endNonZeros () const 141 | { return _M_endNonZeros; } 142 | 143 | private: 144 | int _M_index; 145 | const_iterator _M_begin; 146 | const_iterator _M_end; 147 | const_iterator _M_beginNonZeros; 148 | const_iterator _M_endNonZeros; 149 | }; 150 | 151 | struct _SortUncompressedRow: public std::binary_function 152 | { 153 | inline bool operator () (const UncompressedRow &a, const UncompressedRow &b) const 154 | { return a.count (0) > b.count (0); } 155 | }; 156 | 157 | Compress::Compress () 158 | { 159 | } 160 | 161 | void Compress::operator () (int *table, int row_count, int column_count) 162 | { 163 | index.clear (); 164 | info.clear (); 165 | check.clear (); 166 | 167 | QVector sortedTable (row_count); 168 | 169 | for (int i = 0; i < row_count; ++i) 170 | { 171 | int *begin = &table [i * column_count]; 172 | int *end = begin + column_count; 173 | 174 | sortedTable [i].assign (i, begin, end); 175 | } 176 | 177 | qSort (sortedTable.begin (), sortedTable.end (), _SortUncompressedRow ()); 178 | 179 | #ifndef QLALR_NO_CHECK_SORTED_TABLE 180 | int previous_zeros = INT_MAX; 181 | 182 | foreach (UncompressedRow row, sortedTable) 183 | { 184 | int zeros = row.count (0); 185 | 186 | Q_ASSERT (zeros <= previous_zeros); 187 | zeros = previous_zeros; 188 | qDebug () << "OK!"; 189 | } 190 | #endif 191 | 192 | index.fill (-999999, row_count); 193 | 194 | foreach (UncompressedRow row, sortedTable) 195 | { 196 | int first_token = std::distance (row.begin (), row.beginNonZeros ()); 197 | QVector::iterator pos = info.begin (); 198 | 199 | while (pos != info.end ()) 200 | { 201 | if (pos == info.begin ()) 202 | { 203 | // try to find a perfect match 204 | QVector::iterator pm = std::search (pos, info.end (), row.beginNonZeros (), row.endNonZeros (), _PerfectMatch ()); 205 | 206 | if (pm != info.end ()) 207 | { 208 | pos = pm; 209 | break; 210 | } 211 | } 212 | 213 | pos = std::search (pos, info.end (), row.beginNonZeros (), row.endNonZeros (), _Fit ()); 214 | 215 | if (pos == info.end ()) 216 | break; 217 | 218 | int idx = std::distance (info.begin (), pos) - first_token; 219 | bool conflict = false; 220 | 221 | for (int j = 0; ! conflict && j < row.size (); ++j) 222 | { 223 | if (row.at (j) == 0) 224 | conflict |= idx + j >= 0 && check [idx + j] == j; 225 | 226 | else 227 | conflict |= check [idx + j] == j; 228 | } 229 | 230 | if (! conflict) 231 | break; 232 | 233 | ++pos; 234 | } 235 | 236 | if (pos == info.end ()) 237 | { 238 | int size = info.size (); 239 | 240 | info.resize (info.size () + row.nonZeroElements ()); 241 | check.resize (info.size ()); 242 | 243 | std::fill (check.begin () + size, check.end (), -1); 244 | pos = info.begin () + size; 245 | } 246 | 247 | int offset = std::distance (info.begin (), pos); 248 | index [row.index ()] = offset - first_token; 249 | 250 | for (const int *it = row.beginNonZeros (); it != row.endNonZeros (); ++it, ++pos) 251 | { 252 | if (*it) 253 | *pos = *it; 254 | } 255 | 256 | int i = row.index (); 257 | 258 | for (int j = 0; j < row.size (); ++j) 259 | { 260 | if (row.at (j) == 0) 261 | continue; 262 | 263 | check [index [i] + j] = j; 264 | } 265 | } 266 | 267 | #if 0 268 | foreach (UncompressedRow row, sortedTable) 269 | { 270 | int i = row.index (); 271 | Q_ASSERT (i < sortedTable.size ()); 272 | 273 | for (int j = 0; j < row.size (); ++j) 274 | { 275 | if (row.at (j) == 0) 276 | { 277 | Q_ASSERT (index [i] + j < 0 || check [index [i] + j] != j); 278 | continue; 279 | } 280 | 281 | Q_ASSERT ( info [index [i] + j] == row.at (j)); 282 | Q_ASSERT (check [index [i] + j] == j); 283 | } 284 | } 285 | #endif 286 | } 287 | -------------------------------------------------------------------------------- /doc/global/style/offline.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font: normal 400 14px/1.2 Arial; 3 | margin-top:85px; 4 | font-family: Arial, Helvetica; 5 | color:#313131; 6 | text-align:justify; 7 | margin-left:5px; 8 | margin-right:5px; 9 | } 10 | 11 | img{ 12 | -moz-box-shadow: 3px 3px 3px #ccc; 13 | -webkit-box-shadow: 3px 3px 3px #ccc; 14 | box-shadow: 3px 3px 3px #ccc; 15 | border:#8E8D8D 2px solid; 16 | margin-left:0px; 17 | max-width: 800px; 18 | height: auto 19 | } 20 | 21 | b{ 22 | font-weight:600; 23 | } 24 | 25 | .content{} 26 | 27 | .descr{ 28 | margin-top:35px; 29 | /*max-width: 75%;*/ 30 | margin-left:5px; 31 | text-align:justify; 32 | min-height:700px; 33 | vertical-align:top; 34 | } 35 | 36 | .name{ 37 | max-width: 75%; 38 | font-weight:100; 39 | } 40 | 41 | tt{ 42 | text-align:left;} 43 | 44 | /* 45 | ----------- 46 | links 47 | ----------- 48 | */ 49 | 50 | a:link{ 51 | color: #2C418D; 52 | text-decoration: none; 53 | text-align:left; 54 | } 55 | 56 | a:hover{ 57 | color: #869CD1; 58 | text-decoration:underline; 59 | text-align:left; 60 | } 61 | 62 | a:visited{ 63 | color: #869CD1; 64 | text-decoration: none; 65 | text-align:left; 66 | } 67 | 68 | a:visited:hover{ 69 | text-decoration:underline; 70 | text-align:left; 71 | } 72 | 73 | a[href*="http://"], a[href*="ftp://"],a[href*="https://"] 74 | { 75 | text-decoration: none; 76 | background-image:url(../images/ico_out.png); 77 | background-repeat:no-repeat; 78 | background-position:left; 79 | padding-left:20px; 80 | text-align:left; 81 | } 82 | 83 | .flags{ 84 | text-decoration:none; 85 | text-height:24px; 86 | } 87 | 88 | /* 89 | ------------------------------- 90 | NOTE styles 91 | ------------------------------- 92 | */ 93 | .notetitle, .tiptitle, .fastpathtitle{ 94 | font-weight:bold; 95 | } 96 | 97 | .attentiontitle,.cautiontitle,.dangertitle,.importanttitle,.remembertitle,.restrictiontitle{ 98 | font-weight:bold; 99 | } 100 | 101 | .note,.tip,.fastpath{ 102 | background: #F2F2F2 url(../images/ico_note.png); 103 | background-repeat: no-repeat; 104 | background-position: top left; 105 | padding:5px; 106 | padding-left:40px; 107 | padding-bottom:10px; 108 | border:#999 1px dotted; 109 | color:#666666; 110 | margin:5px; 111 | } 112 | 113 | .attention,.caution,.danger,.important,.remember,.restriction{ 114 | background: #F2F2F2 url(../images/ico_note_attention.png); 115 | background-repeat:no-repeat; 116 | background-position:top left; 117 | padding:5px; 118 | padding-left:40px; 119 | padding-bottom:10px; 120 | border:#999 1px dotted; 121 | color:#666666; 122 | margin:5px; 123 | } 124 | 125 | /* 126 | ------------------------------- 127 | Top navigation 128 | ------------------------------- 129 | */ 130 | 131 | .header{ 132 | 133 | height:1px; 134 | padding:0px; 135 | margin:0px; 136 | } 137 | 138 | .qtref{ 139 | display: block; 140 | position: relative; 141 | top: -76px; 142 | height:15px; 143 | z-index: 1; 144 | font-size:11px; 145 | padding-right:10px; 146 | float:right; 147 | } 148 | 149 | .naviNextPrevious{ 150 | display: block; 151 | position: relative; 152 | text-align: right; 153 | top: -53px; 154 | float:right; 155 | height:20px; 156 | z-index:1; 157 | padding-right:10px; 158 | padding-top:2px; 159 | vertical-align:top; 160 | margin:0px; 161 | } 162 | 163 | 164 | .naviNextPrevious > a:first-child{ 165 | background-image:url(../images/btn_prev.png); 166 | background-repeat:no-repeat; 167 | background-position:left; 168 | padding-left:20px; 169 | height:20px; 170 | padding-left:20px; 171 | } 172 | 173 | .naviNextPrevious > a:last-child{ 174 | background-image:url(../images/btn_next.png); 175 | background-repeat:no-repeat; 176 | background-position:right; 177 | padding-right:20px; 178 | height:20px; 179 | margin-left:30px; 180 | } 181 | 182 | .breadcrumb{ 183 | display: block; 184 | position: relative; 185 | top:-20px; 186 | /*border-top:2px solid #ffffff;*/ 187 | border-bottom: 1px solid #cecece; 188 | background-color:#F2F2F2; 189 | z-index:1; 190 | height:20px; 191 | padding:0px; 192 | margin:0px; 193 | padding-left:10px; 194 | padding-top:2px; 195 | margin-left:-5px; 196 | margin-right:-5px; 197 | } 198 | 199 | .breadcrumb ul{ 200 | margin:0px; 201 | padding:0px; 202 | } 203 | 204 | .breadcrumb ul li{ 205 | background-color:#F2F2F2; 206 | list-style-type:none; 207 | padding:0; 208 | margin:0; 209 | height:20px; 210 | } 211 | 212 | .breadcrumb li{ 213 | float:left; 214 | } 215 | 216 | .breadcrumb .first { 217 | background:url(../images/home.png); 218 | background-position:left; 219 | background-repeat:no-repeat; 220 | padding-left:20px; 221 | } 222 | 223 | 224 | .breadcrumb li a{ 225 | color:#2C418D; 226 | display:block; 227 | text-decoration:none; 228 | background:url(../images/arrow.png); 229 | background-repeat:no-repeat; 230 | background-position:right; 231 | padding-right:25px; 232 | padding-left:10px; 233 | } 234 | 235 | .breadcrumb li a:hover{ 236 | color:#909090; 237 | display:block; 238 | text-decoration:none; 239 | background:url(../images/arrow.png); 240 | background-repeat:no-repeat; 241 | background-position:right; 242 | padding-right:20px; 243 | padding-left:10px; 244 | } 245 | 246 | 247 | /* table of content 248 | no display 249 | */ 250 | 251 | /* 252 | ----------- 253 | headers 254 | ----------- 255 | */ 256 | 257 | 258 | @media screen{ 259 | .title{ 260 | color:#313131; 261 | font-size: 18px; 262 | font-weight: normal; 263 | left: 0; 264 | padding-bottom: 20px; 265 | padding-left: 10px; 266 | padding-top: 20px; 267 | position: absolute; 268 | right: 0; 269 | top: 0; 270 | background-color:#E6E6E6; 271 | border-bottom: 1px #CCC solid; 272 | border-top: 2px #CCC solid; 273 | font-weight:bold; 274 | margin-left:0px; 275 | margin-right:0px; 276 | } 277 | } 278 | 279 | h1 { 280 | margin: 0; 281 | } 282 | 283 | h2, p.h2 { 284 | font: 500 16px/1.2 Arial; 285 | font-weight:100; 286 | background-color:#F2F3F4; 287 | padding:4px; 288 | margin-bottom:30px; 289 | margin-top:30px; 290 | border-top:#E0E0DE 1px solid; 291 | border-bottom: #E0E0DE 1px solid; 292 | max-width: 99%; 293 | } 294 | 295 | h3{ 296 | 297 | font: 500 14px/1.2 Arial; 298 | font-weight:100; 299 | text-decoration:underline; 300 | margin-bottom:30px; 301 | margin-top:30px; 302 | } 303 | 304 | h3.fn,span.fn{ 305 | border-width: 1px; 306 | border-style: solid; 307 | border-color: #E6E6E6; 308 | -moz-border-radius: 7px 7px 7px 7px; 309 | -webkit-border-radius: 7px 7px 7px 7px; 310 | border-radius: 7px 7px 7px 7px; 311 | background-color: #F6F6F6; 312 | word-spacing: 3px; 313 | padding: 5px 5px; 314 | text-decoration:none; 315 | font-weight:bold; 316 | max-width:75%; 317 | font-size:14px; 318 | margin:0px; 319 | margin-top:30px; 320 | 321 | } 322 | 323 | .name{ 324 | color:#1A1A1A; 325 | } 326 | .type{ 327 | color:#808080; 328 | } 329 | 330 | 331 | 332 | @media print { 333 | .title { 334 | color:#0066CB; 335 | font-family:Arial, Helvetica; 336 | font-size: 32px; 337 | font-weight: normal; 338 | left: 0; 339 | position: absolute; 340 | right: 0; 341 | top: 0; 342 | } 343 | } 344 | 345 | 346 | /* 347 | ----------------- 348 | table styles 349 | ----------------- 350 | */ 351 | .table img { 352 | border:none; 353 | margin-left:0px; 354 | -moz-box-shadow:0px 0px 0px #fff; 355 | -webkit-box-shadow: 0px 0px 0px #fff; 356 | box-shadow: 0px 0px 0px #fff; 357 | } 358 | 359 | /* table with border alternative colours*/ 360 | 361 | table,pre{ 362 | -moz-border-radius: 7px 7px 7px 7px; 363 | -webkit-border-radius: 7px 7px 7px 7px; 364 | border-radius: 7px 7px 7px 7px; 365 | background-color: #F6F6F6; 366 | border: 1px solid #E6E6E6; 367 | border-collapse: separate; 368 | font-size: 12px; 369 | line-height: 1.2; 370 | margin-bottom: 25px; 371 | margin-left: 15px; 372 | font-size: 12px; 373 | line-height: 1.2; 374 | margin-bottom: 25px; 375 | margin-left: 15px; 376 | } 377 | 378 | 379 | table th{ 380 | text-align:left; 381 | padding-left:20px; 382 | } 383 | 384 | table td { 385 | padding: 3px 15px 3px 20px; 386 | border-bottom:#CCC dotted 1px; 387 | } 388 | table p { margin:0px;} 389 | 390 | table tr.even { 391 | background-color: white; 392 | color: #66666E; 393 | } 394 | 395 | table tr.odd { 396 | background-color: #F6F6F6; 397 | color: #66666E; 398 | } 399 | 400 | 401 | table thead { 402 | text-align:left; 403 | padding-left:20px; 404 | background-color:#e1e0e0; 405 | border-left:none; 406 | border-right:none; 407 | } 408 | 409 | table thead th { 410 | padding-top:5px; 411 | padding-left:10px; 412 | padding-bottom:5px; 413 | border-bottom: 2px solid #D1D1D1; 414 | padding-right:10px; 415 | } 416 | 417 | 418 | /* table bodless & white*/ 419 | 420 | .borderless { 421 | border-radius: 0px 0px 0px 0px; 422 | background-color: #fff; 423 | border: 1px solid #fff; 424 | } 425 | 426 | .borderless tr { 427 | background-color: #FFF; 428 | color: #66666E; 429 | } 430 | 431 | .borderless td { 432 | border:none; 433 | border-bottom:#fff dotted 1px; 434 | } 435 | 436 | /* 437 | ----------- 438 | List 439 | ----------- 440 | */ 441 | 442 | ul{ 443 | padding-bottom:2px; 444 | } 445 | 446 | li { 447 | margin-bottom: 10px; 448 | padding-left: 8px; 449 | list-style:outside; 450 | list-style-type:square; 451 | text-align:left; 452 | } 453 | 454 | 455 | ol{ 456 | margin:10px; 457 | padding:0; 458 | } 459 | 460 | ol > li{ 461 | margin-left: 30px; 462 | padding-left:8px; 463 | list-style:decimal; 464 | } 465 | 466 | .centerAlign{ 467 | text-align: left; 468 | } 469 | 470 | .cpp{ 471 | display: block; 472 | margin: 10; 473 | overflow: hidden; 474 | overflow-x: hidden; 475 | overflow-y: hidden; 476 | padding: 20px 0 20px 0; 477 | } 478 | 479 | .footer{ 480 | margin-top: 50px; 481 | padding-left:5px; 482 | margin-bottom: 10px; 483 | font-size:10px; 484 | border-top: 1px solid #999; 485 | padding-top:11px; 486 | } 487 | 488 | .footerNavi{ 489 | width:auto; 490 | text-align:right; 491 | margin-top:50px; 492 | z-index:1; 493 | } 494 | 495 | .memItemLeft{ 496 | padding-right: 3px; 497 | } 498 | 499 | .memItemRight{ 500 | padding: 3px 15px 3px 0; 501 | } 502 | 503 | .qml{ 504 | display: block; 505 | margin: 10; 506 | overflow: hidden; 507 | overflow-x: hidden; 508 | overflow-y: hidden; 509 | padding: 20px 0 20px 0; 510 | } 511 | 512 | .qmldefault{ 513 | padding-left: 5px; 514 | float: right; 515 | color: red; 516 | } 517 | 518 | .qmlreadonly{ 519 | padding-left: 5px; 520 | float: right; 521 | color: #254117; 522 | } 523 | 524 | .rightAlign{ 525 | padding: 3px 5px 3px 10px; 526 | text-align: right; 527 | } 528 | 529 | /* 530 | ----------- 531 | Content table 532 | ----------- 533 | */ 534 | 535 | @media print{ 536 | .toc { 537 | float: right; 538 | padding-bottom: 10px; 539 | padding-top: 50px; 540 | width: 100%; 541 | background-image:url(../images/bgrContent.png); 542 | background-position:top; 543 | background-repeat:no-repeat; 544 | } 545 | } 546 | 547 | @media screen{ 548 | .toc{ 549 | clear:both; 550 | float:right; 551 | vertical-align:top; 552 | -moz-border-radius: 7px 7px 7px 7px; 553 | -webkit-border-radius: 7px 7px 7px 7px; 554 | border-radius: 7px 7px 7px 7px; 555 | background:#FFF url(../images/bgrContent.png); 556 | background-position:top; 557 | background-repeat:repeat-x; 558 | border: 1px solid #E6E6E6; 559 | padding-left:5px; 560 | padding-bottom:10px; 561 | height: auto; 562 | width: 200px; 563 | text-align:left; 564 | z-index:2; 565 | margin-left:20px; 566 | margin-right:20px; 567 | margin-top:0px; 568 | padding-top:0px; 569 | } 570 | } 571 | 572 | .toc h3{ 573 | text-decoration:none; 574 | } 575 | 576 | .toc h3{font: 500 14px/1.2 Arial; 577 | font-weight:100; 578 | padding:0px; 579 | margin:0px; 580 | padding-top:5px; 581 | padding-left:5px; 582 | } 583 | 584 | 585 | .toc ul{ 586 | width:160px; 587 | padding-left:10px; 588 | padding-right:5px; 589 | padding-bottom:10px; 590 | padding-top:10px; 591 | } 592 | 593 | .toc ul li{ 594 | margin-left:20px; 595 | list-style-image:url(../images/blu_dot.png); 596 | list-style:outside; 597 | 598 | } 599 | 600 | 601 | .toc ul li a:link{ 602 | color: #2C418D; 603 | text-decoration: none; 604 | } 605 | 606 | .toc ul li a:hover{ 607 | color: #869CD1; 608 | text-decoration:underline; 609 | 610 | } 611 | 612 | .toc ul li a:visited{ 613 | color: #869CD1; 614 | font-weight: bold; 615 | } 616 | 617 | .level1{ 618 | border:none;} 619 | 620 | .clearfix{ 621 | clear:both;} 622 | 623 | -------------------------------------------------------------------------------- /src/lalr.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #ifndef LALR_H 43 | #define LALR_H 44 | 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | class Rule; 56 | class State; 57 | class Grammar; 58 | class Item; 59 | class State; 60 | class Arrow; 61 | class Automaton; 62 | 63 | template 64 | class OrderedSet : protected QMap<_Tp, bool> 65 | { 66 | typedef QMap<_Tp, bool> _Base; 67 | 68 | public: 69 | class const_iterator 70 | { 71 | typename _Base::const_iterator _M_iterator; 72 | 73 | public: 74 | const_iterator () {} 75 | 76 | const_iterator (const typename _Base::const_iterator &it): 77 | _M_iterator (it) {} 78 | 79 | const _Tp &operator * () const 80 | { return _M_iterator.key (); } 81 | 82 | const _Tp *operator -> () const 83 | { return &_M_iterator.key (); } 84 | 85 | const_iterator &operator ++ () 86 | { ++_M_iterator; return *this; } 87 | 88 | const_iterator operator ++ (int) const 89 | { 90 | const_iterator me (*this); 91 | ++_M_iterator; 92 | return me; 93 | } 94 | 95 | bool operator == (const const_iterator &other) const 96 | { return _M_iterator == other._M_iterator; } 97 | 98 | bool operator != (const const_iterator &other) const 99 | { return _M_iterator != other._M_iterator; } 100 | }; 101 | 102 | typedef const_iterator iterator; 103 | 104 | public: 105 | OrderedSet () {} 106 | 107 | const_iterator begin () const 108 | { return const_iterator (_Base::begin ()); } 109 | 110 | const_iterator end () const 111 | { return const_iterator (_Base::end ()); } 112 | 113 | bool isEmpty () const 114 | { return _Base::isEmpty (); } 115 | 116 | int size () const 117 | { return _Base::size (); } 118 | 119 | const_iterator find (const _Tp &elt) const 120 | { return const_iterator (_Base::find (elt)); } 121 | 122 | QPair insert (const _Tp &elt) 123 | { 124 | int elts = _Base::size (); 125 | const_iterator it (_Base::insert (typename _Base::key_type (elt), true)); 126 | return qMakePair (it, elts != _Base::size ()); 127 | } 128 | 129 | QPair insert (const_iterator, const _Tp &elt) 130 | { 131 | int elts = _Base::size (); 132 | const_iterator it (_Base::insert (typename _Base::key_type (elt), true)); 133 | return qMakePair (it, elts != _Base::size ()); 134 | } 135 | 136 | const _Tp &operator [] (const _Tp &elt) 137 | { return *insert (elt)->first; } 138 | 139 | template 140 | void insert (_InputIterator first, _InputIterator last) 141 | { 142 | for (; first != last; ++first) 143 | insert (*first); 144 | } 145 | }; 146 | 147 | // names 148 | typedef QLinkedList::iterator Name; 149 | typedef QLinkedList NameList; 150 | typedef OrderedSet NameSet; 151 | 152 | // items 153 | typedef QLinkedList ItemList; 154 | typedef ItemList::iterator ItemPointer; 155 | 156 | // rules 157 | typedef QLinkedList debug_infot; 158 | typedef debug_infot::iterator RulePointer; 159 | typedef QMultiMap RuleMap; 160 | 161 | // states 162 | typedef QLinkedList StateList; 163 | typedef StateList::iterator StatePointer; 164 | 165 | // arrows 166 | typedef QMap Bundle; 167 | 168 | class Rule 169 | { 170 | public: 171 | void clear () 172 | { 173 | lhs = Name (); 174 | rhs.clear (); 175 | prec = Name (); 176 | } 177 | 178 | public: 179 | Name lhs; 180 | NameList rhs; 181 | Name prec; 182 | }; 183 | 184 | class Lookback 185 | { 186 | public: 187 | Lookback (StatePointer s, Name n): 188 | state (s), nt (n) {} 189 | 190 | inline bool operator == (const Lookback &other) const 191 | { return state == other.state && nt == other.nt; } 192 | 193 | inline bool operator != (const Lookback &other) const 194 | { return state != other.state || nt != other.nt; } 195 | 196 | bool operator < (const Lookback &other) const; 197 | 198 | public: 199 | StatePointer state; 200 | Name nt; 201 | }; 202 | 203 | class Item 204 | { 205 | public: 206 | inline NameList::iterator begin_rhs () const 207 | { return rule->rhs.begin (); } 208 | 209 | inline NameList::iterator end_rhs () const 210 | { return rule->rhs.end (); } 211 | 212 | inline bool operator == (const Item &other) const 213 | { return rule == other.rule && dot == other.dot; } 214 | 215 | inline bool operator != (const Item &other) const 216 | { return rule != other.rule || dot != other.dot; } 217 | 218 | inline bool isReduceItem () const 219 | { return dot == rule->rhs.end (); } 220 | 221 | Item next () const; 222 | 223 | public: 224 | RulePointer rule; 225 | NameList::iterator dot; 226 | }; 227 | 228 | class State 229 | { 230 | public: 231 | State (Grammar *grammar); 232 | 233 | inline bool operator == (const State &other) const 234 | { return kernel == other.kernel; } 235 | 236 | inline bool operator != (const State &other) const 237 | { return kernel != other.kernel; } 238 | 239 | QPair insert (const Item &item); 240 | QPair insertClosure (const Item &item); 241 | 242 | public: // attributes 243 | ItemList kernel; 244 | ItemList closure; 245 | Bundle bundle; 246 | QMap reads; 247 | QMap follows; 248 | RulePointer defaultReduce; 249 | }; 250 | 251 | ///////////////////////////////////////////////////////////// 252 | // digraph 253 | ///////////////////////////////////////////////////////////// 254 | template 255 | class Node 256 | { 257 | public: 258 | typedef OrderedSet > Repository; 259 | typedef typename Repository::iterator iterator; 260 | typedef typename QLinkedList::iterator edge_iterator; 261 | 262 | public: 263 | static iterator get (_Tp data); 264 | 265 | QPair insertEdge (iterator other) const; 266 | 267 | inline edge_iterator begin () const 268 | { return outs.begin (); } 269 | 270 | inline edge_iterator end () const 271 | { return outs.end (); } 272 | 273 | inline bool operator == (const Node<_Tp> &other) const 274 | { return data == other.data; } 275 | 276 | inline bool operator != (const Node<_Tp> &other) const 277 | { return data != other.data; } 278 | 279 | inline bool operator < (const Node<_Tp> &other) const 280 | { return data < other.data; } 281 | 282 | static inline iterator begin_nodes () 283 | { return repository ().begin (); } 284 | 285 | static inline iterator end_nodes () 286 | { return repository ().end (); } 287 | 288 | static Repository &repository () 289 | { 290 | static Repository r; 291 | return r; 292 | } 293 | 294 | public: // attributes 295 | mutable bool root; 296 | mutable int dfn; 297 | mutable _Tp data; 298 | mutable QLinkedList outs; 299 | 300 | protected: 301 | inline Node () {} 302 | 303 | inline Node (_Tp d): 304 | root (true), dfn (0), data (d) {} 305 | }; 306 | 307 | template 308 | typename Node<_Tp>::iterator Node<_Tp>::get (_Tp data) 309 | { 310 | Node<_Tp> tmp (data); 311 | iterator it = repository ().find (tmp); 312 | 313 | if (it != repository ().end ()) 314 | return it; 315 | 316 | return repository ().insert (tmp).first; 317 | } 318 | 319 | template 320 | QPair::iterator>::iterator, bool> Node<_Tp>::insertEdge (typename Node<_Tp>::iterator other) const 321 | { 322 | edge_iterator it = qFind (outs.begin (), outs.end (), other); 323 | 324 | if (it != outs.end ()) 325 | return qMakePair (it, false); 326 | 327 | other->root = false; 328 | return qMakePair (outs.insert (outs.end (), other), true); 329 | } 330 | 331 | ///////////////////////////////////////////////////////////// 332 | // Grammar 333 | ///////////////////////////////////////////////////////////// 334 | class Grammar 335 | { 336 | public: 337 | Grammar (); 338 | 339 | Name intern (const QString &id); 340 | 341 | inline bool isTerminal (Name name) const 342 | { return terminals.find (name) != terminals.end (); } 343 | 344 | inline bool isNonTerminal (Name name) const 345 | { return non_terminals.find (name) != non_terminals.end (); } 346 | 347 | void buildRuleMap (); 348 | void buildExtendedGrammar (); 349 | 350 | public: 351 | QString merged_output; 352 | QString table_name; 353 | QString decl_file_name; 354 | QString impl_file_name; 355 | QString token_prefix; 356 | QLinkedList names; 357 | Name start; 358 | NameSet terminals; 359 | NameSet non_terminals; 360 | QMap spells; 361 | debug_infot rules; 362 | RuleMap rule_map; 363 | RulePointer goal; 364 | Name tk_end; 365 | Name accept_symbol; 366 | NameSet declared_lhs; 367 | int expected_shift_reduce; 368 | int expected_reduce_reduce; 369 | 370 | enum Assoc { 371 | NonAssoc, 372 | Left, 373 | Right 374 | }; 375 | 376 | struct TokenInfo { 377 | Assoc assoc; 378 | int prec; 379 | }; 380 | 381 | QMap token_info; 382 | Assoc current_assoc; 383 | int current_prec; 384 | }; 385 | 386 | class Read 387 | { 388 | public: 389 | inline Read () {} 390 | 391 | inline Read (StatePointer s, Name n): 392 | state (s), nt (n) {} 393 | 394 | inline bool operator == (const Read &other) const 395 | { return state == other.state && nt == other.nt; } 396 | 397 | inline bool operator != (const Read &other) const 398 | { return state != other.state || nt != other.nt; } 399 | 400 | bool operator < (const Read &other) const; 401 | 402 | public: 403 | StatePointer state; 404 | Name nt; 405 | }; 406 | 407 | class Include 408 | { 409 | public: 410 | inline Include () {} 411 | 412 | inline Include (StatePointer s, Name n): 413 | state (s), nt (n) {} 414 | 415 | inline bool operator == (const Include &other) const 416 | { return state == other.state && nt == other.nt; } 417 | 418 | inline bool operator != (const Include &other) const 419 | { return state != other.state || nt != other.nt; } 420 | 421 | bool operator < (const Include &other) const; 422 | 423 | public: 424 | StatePointer state; 425 | Name nt; 426 | }; 427 | 428 | class Automaton 429 | { 430 | public: 431 | Automaton (Grammar *g); 432 | 433 | QPair internState (const State &state); 434 | 435 | typedef Node ReadsGraph; 436 | typedef ReadsGraph::iterator ReadNode; 437 | 438 | typedef Node IncludesGraph; 439 | typedef IncludesGraph::iterator IncludeNode; 440 | 441 | void build (); 442 | void buildNullables (); 443 | 444 | void buildLookbackSets (); 445 | 446 | void buildDirectReads (); 447 | void buildReadsDigraph (); 448 | void buildReads (); 449 | void visitReadNode (ReadNode node); 450 | 451 | void buildIncludesAndFollows (); 452 | void buildIncludesDigraph (); 453 | void visitIncludeNode (IncludeNode node); 454 | 455 | void buildLookaheads (); 456 | 457 | void buildDefaultReduceActions (); 458 | 459 | void closure (StatePointer state); 460 | 461 | int id (RulePointer rule); 462 | int id (StatePointer state); 463 | int id (Name name); 464 | 465 | void dump (QTextStream &out, IncludeNode incl); 466 | void dump (QTextStream &out, ReadNode rd); 467 | void dump (QTextStream &out, const Lookback &lp); 468 | 469 | public: // ### private 470 | Grammar *_M_grammar; 471 | StateList states; 472 | StatePointer start; 473 | NameSet nullables; 474 | QMultiMap lookbacks; 475 | QMap lookaheads; 476 | 477 | private: 478 | QStack _M_reads_stack; 479 | int _M_reads_dfn; 480 | 481 | QStack _M_includes_stack; 482 | int _M_includes_dfn; 483 | }; 484 | 485 | QT_BEGIN_NAMESPACE 486 | bool operator < (Name a, Name b); 487 | bool operator < (StatePointer a, StatePointer b); 488 | bool operator < (ItemPointer a, ItemPointer b); 489 | QT_END_NAMESPACE 490 | 491 | QTextStream &operator << (QTextStream &out, const Name &n); 492 | QTextStream &operator << (QTextStream &out, const Rule &r); 493 | QTextStream &operator << (QTextStream &out, const Item &item); 494 | QTextStream &operator << (QTextStream &out, const NameSet &ns); 495 | 496 | QT_BEGIN_NAMESPACE 497 | // ... hmm 498 | extern QTextStream qerr; 499 | extern QTextStream qout; 500 | QT_END_NAMESPACE 501 | 502 | #endif // LALR_H 503 | -------------------------------------------------------------------------------- /src/recognizer.cpp: -------------------------------------------------------------------------------- 1 | 2 | /**************************************************************************** 3 | ** 4 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 5 | ** Contact: http://www.qt-project.org/legal 6 | ** 7 | ** This file is part of the QLALR project on Qt Labs. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL$ 10 | ** Commercial License Usage 11 | ** Licensees holding valid commercial Qt licenses may use this file in 12 | ** accordance with the commercial license agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and Digia. For licensing terms and 15 | ** conditions see http://qt.digia.com/licensing. For further information 16 | ** use the contact form at http://qt.digia.com/contact-us. 17 | ** 18 | ** GNU Lesser General Public License Usage 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser 20 | ** General Public License version 2.1 as published by the Free Software 21 | ** Foundation and appearing in the file LICENSE.LGPL included in the 22 | ** packaging of this file. Please review the following information to 23 | ** ensure the GNU Lesser General Public License version 2.1 requirements 24 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 | ** 26 | ** In addition, as a special exception, Digia gives you certain additional 27 | ** rights. These rights are described in the Digia Qt LGPL Exception 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 | ** 30 | ** GNU General Public License Usage 31 | ** Alternatively, this file may be used under the terms of the GNU 32 | ** General Public License version 3.0 as published by the Free Software 33 | ** Foundation and appearing in the file LICENSE.GPL included in the 34 | ** packaging of this file. Please review the following information to 35 | ** ensure the GNU General Public License version 3.0 requirements will be 36 | ** met: http://www.gnu.org/copyleft/gpl.html. 37 | ** 38 | ** 39 | ** $QT_END_LICENSE$ 40 | ** 41 | ****************************************************************************/ 42 | 43 | #include "recognizer.h" 44 | #include 45 | #include 46 | #include 47 | 48 | Recognizer::Recognizer (Grammar *grammar, bool no_lines): 49 | tos(0), 50 | stack_size(0), 51 | state_stack(0), 52 | _M_line(1), 53 | _M_action_line(0), 54 | _M_grammar(grammar), 55 | _M_no_lines(no_lines) 56 | { 57 | } 58 | 59 | Recognizer::~Recognizer() 60 | { 61 | if (stack_size) 62 | ::free(state_stack); 63 | } 64 | 65 | inline void Recognizer::reallocateStack() 66 | { 67 | if (! stack_size) 68 | stack_size = 128; 69 | else 70 | stack_size <<= 1; 71 | 72 | sym_stack.resize (stack_size); 73 | 74 | if (! state_stack) 75 | state_stack = reinterpret_cast (::malloc(stack_size * sizeof(int))); 76 | else 77 | state_stack = reinterpret_cast (::realloc(state_stack, stack_size * sizeof(int))); 78 | } 79 | 80 | int Recognizer::nextToken() 81 | { 82 | QString text; 83 | 84 | Lagain: 85 | while (ch.isSpace ()) 86 | inp (); 87 | 88 | if (ch.isNull ()) 89 | return EOF_SYMBOL; 90 | 91 | int token = ch.unicode (); 92 | 93 | if (token == '"') 94 | { 95 | inp(); // skip " 96 | text.clear (); 97 | while (! ch.isNull () && ch != QLatin1Char ('"')) 98 | { 99 | if (ch == QLatin1Char ('\\')) 100 | { 101 | text += ch; 102 | inp(); 103 | } 104 | text += ch; 105 | inp (); 106 | } 107 | 108 | if (ch == QLatin1Char ('"')) 109 | inp (); 110 | else 111 | qerr << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; 112 | 113 | _M_current_value = text; 114 | return (token = STRING_LITERAL); 115 | } 116 | 117 | else if (ch.isLetterOrNumber () || ch == QLatin1Char ('_')) 118 | { 119 | text.clear (); 120 | do { text += ch; inp (); } 121 | while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('.')); 122 | _M_current_value = text; 123 | return (token = ID); 124 | } 125 | 126 | else if (token == '%') 127 | { 128 | text.clear (); 129 | 130 | do { inp (); } 131 | while (ch.isSpace ()); 132 | 133 | do { text += ch; inp (); } 134 | while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('-')); 135 | 136 | if (text == QLatin1String("token_prefix")) 137 | return (token = TOKEN_PREFIX); 138 | else if (text == QLatin1String("merged_output")) 139 | return (token = MERGED_OUTPUT); 140 | else if (text == QLatin1String("token")) 141 | return (token = TOKEN); 142 | else if (text == QLatin1String("start")) 143 | return (token = START); 144 | else if (text == QLatin1String("parser")) 145 | return (token = PARSER); 146 | else if (text == QLatin1String("decl")) 147 | return (token = DECL_FILE); 148 | else if (text == QLatin1String("impl")) 149 | return (token = IMPL_FILE); 150 | else if (text == QLatin1String("expect")) 151 | return (token = EXPECT); 152 | else if (text == QLatin1String("expect-rr")) 153 | return (token = EXPECT_RR); 154 | else if (text == QLatin1String("left")) 155 | return (token = LEFT); 156 | else if (text == QLatin1String("right")) 157 | return (token = RIGHT); 158 | else if (text == QLatin1String("nonassoc")) 159 | return (token = NONASSOC); 160 | else if (text == QLatin1String("prec")) 161 | return (token = PREC); 162 | else 163 | { 164 | qerr << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; 165 | exit (EXIT_FAILURE); 166 | return (token = ERROR); 167 | } 168 | } 169 | 170 | inp (); 171 | 172 | if (token == '-' && ch == QLatin1Char ('-')) 173 | { 174 | do { inp (); } 175 | while (! ch.isNull () && ch != QLatin1Char ('\n')); 176 | goto Lagain; 177 | } 178 | 179 | else if (token == ':' && ch == QLatin1Char (':')) 180 | { 181 | inp (); 182 | if (ch != QLatin1Char ('=')) 183 | return (token = ERROR); 184 | inp (); 185 | return (token = COLON); 186 | } 187 | 188 | else if (token == '/' && ch == QLatin1Char (':')) 189 | { 190 | _M_action_line = _M_line; 191 | 192 | text.clear (); 193 | if (! _M_no_lines) 194 | text += QLatin1String ("\n#line ") + QString::number (_M_action_line) + " \"" + _M_input_file + "\"\n"; 195 | inp (); // skip ':' 196 | 197 | forever 198 | { 199 | while (! ch.isNull ()) 200 | { 201 | token = ch.unicode (); 202 | inp (); 203 | 204 | if (token == ':' && ch == QLatin1Char ('/')) 205 | break; 206 | 207 | text += QLatin1Char (token); 208 | } 209 | 210 | if (ch != QLatin1Char ('/')) 211 | return (token = ERROR); 212 | 213 | inp (); 214 | 215 | if (ch.isNull () || ch.isSpace ()) 216 | { 217 | _M_current_value = text; 218 | return (token = DECL); 219 | } 220 | else 221 | text += QLatin1String (":/"); 222 | } 223 | } 224 | 225 | else if (token == '/' && ch == QLatin1Char ('.')) 226 | { 227 | _M_action_line = _M_line; 228 | 229 | text.clear (); 230 | if (! _M_no_lines) 231 | text += QLatin1String ("\n#line ") + QString::number (_M_action_line) + " \"" + _M_input_file + "\"\n"; 232 | 233 | inp (); // skip ':' 234 | 235 | forever 236 | { 237 | while (! ch.isNull ()) 238 | { 239 | token = ch.unicode (); 240 | inp (); 241 | 242 | if (token == '.' && ch == QLatin1Char ('/')) 243 | break; 244 | 245 | text += QLatin1Char (token); 246 | } 247 | 248 | if (ch != QLatin1Char ('/')) 249 | return (token = ERROR); 250 | 251 | inp (); 252 | 253 | if (ch.isNull () || ch.isSpace ()) 254 | { 255 | _M_current_value = text; 256 | return (token = IMPL); 257 | } 258 | else 259 | text += QLatin1String (""); 260 | } 261 | } 262 | 263 | switch (token) { 264 | case ':': 265 | return (token = COLON); 266 | 267 | case ';': 268 | return (token = SEMICOLON); 269 | 270 | case '|': 271 | return (token = OR); 272 | 273 | default: 274 | break; 275 | } 276 | 277 | return token; 278 | } 279 | 280 | bool Recognizer::parse (const QString &input_file) 281 | { 282 | _M_input_file = input_file; 283 | 284 | QFile file(_M_input_file); 285 | if (! file.open(QFile::ReadOnly)) 286 | { 287 | qerr << "qlalr: no input file\n"; 288 | return false; 289 | } 290 | 291 | QString _M_contents = QTextStream(&file).readAll(); 292 | _M_firstChar = _M_contents.constBegin(); 293 | _M_lastChar = _M_contents.constEnd(); 294 | _M_currentChar = _M_firstChar; 295 | _M_line = 1; 296 | 297 | int yytoken = -1; 298 | inp (); 299 | 300 | reallocateStack(); 301 | 302 | _M_current_rule = _M_grammar->rules.end (); 303 | _M_decls.clear (); 304 | _M_impls.clear (); 305 | 306 | tos = 0; 307 | state_stack[++tos] = 0; 308 | 309 | while (true) 310 | { 311 | if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]]) 312 | yytoken = nextToken(); 313 | 314 | int act = t_action (state_stack [tos], yytoken); 315 | 316 | if (act == ACCEPT_STATE) 317 | return true; 318 | 319 | else if (act > 0) 320 | { 321 | if (++tos == stack_size) 322 | reallocateStack(); 323 | 324 | sym_stack [tos] = _M_current_value; 325 | state_stack [tos] = act; 326 | yytoken = -1; 327 | } 328 | 329 | else if (act < 0) 330 | { 331 | int r = - act - 1; 332 | 333 | tos -= rhs [r]; 334 | act = state_stack [tos++]; 335 | 336 | switch (r) { 337 | 338 | case 3: { 339 | Name name = _M_grammar->intern (sym(2)); 340 | _M_grammar->start = name; 341 | _M_grammar->non_terminals.insert (name); 342 | } break; 343 | 344 | case 5: { 345 | _M_grammar->table_name = sym(2); 346 | } break; 347 | 348 | case 6: { 349 | _M_grammar->merged_output = sym(2); 350 | } break; 351 | 352 | case 7: { 353 | _M_grammar->decl_file_name = sym(2); 354 | } break; 355 | 356 | case 8: { 357 | _M_grammar->impl_file_name = sym(2); 358 | } break; 359 | 360 | case 9: { 361 | _M_grammar->expected_shift_reduce = sym(2).toInt(); 362 | } break; 363 | 364 | case 10: { 365 | _M_grammar->expected_reduce_reduce = sym(2).toInt(); 366 | } break; 367 | 368 | case 11: { 369 | _M_grammar->token_prefix = sym(2); 370 | } break; 371 | case 17:case 18: { 372 | Name name = _M_grammar->intern (sym(1)); 373 | _M_grammar->terminals.insert (name); 374 | _M_grammar->spells.insert (name, sym(2)); 375 | } break; 376 | 377 | case 19: { 378 | _M_grammar->current_assoc = Grammar::Left; 379 | ++_M_grammar->current_prec; 380 | } break; 381 | 382 | case 20: { 383 | _M_grammar->current_assoc = Grammar::Right; 384 | ++_M_grammar->current_prec; 385 | } break; 386 | 387 | case 21: { 388 | _M_grammar->current_assoc = Grammar::NonAssoc; 389 | ++_M_grammar->current_prec; 390 | } break; 391 | 392 | case 25: { 393 | Name name = _M_grammar->intern (sym(1)); 394 | _M_grammar->terminals.insert (name); 395 | 396 | Grammar::TokenInfo info; 397 | info.prec = _M_grammar->current_prec; 398 | info.assoc = _M_grammar->current_assoc; 399 | _M_grammar->token_info.insert (name, info); 400 | } break; 401 | 402 | case 26: { 403 | _M_decls += expand (sym(1)); 404 | } break; 405 | 406 | case 27: { 407 | _M_impls += expand (sym(1)); 408 | } break; 409 | 410 | case 34: { 411 | _M_current_rule = _M_grammar->rules.insert (_M_grammar->rules.end (), Rule ()); 412 | _M_current_rule->lhs = _M_grammar->intern (sym(1)); 413 | _M_grammar->declared_lhs.insert (_M_current_rule->lhs); 414 | 415 | if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) 416 | { 417 | qerr << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; 418 | return false; 419 | } 420 | 421 | _M_grammar->non_terminals.insert (_M_current_rule->lhs); 422 | } break; 423 | 424 | case 38: { 425 | Name lhs = _M_current_rule->lhs; 426 | _M_current_rule = _M_grammar->rules.insert (_M_grammar->rules.end (), Rule ()); 427 | _M_current_rule->lhs = lhs; 428 | _M_grammar->declared_lhs.insert (_M_current_rule->lhs); 429 | 430 | if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) 431 | { 432 | qerr << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; 433 | return false; 434 | } 435 | 436 | _M_grammar->non_terminals.insert (_M_current_rule->lhs); 437 | } break; 438 | 439 | case 39: { 440 | _M_current_rule->prec = _M_grammar->names.end (); 441 | 442 | for (NameList::iterator it = _M_current_rule->rhs.begin (); it != _M_current_rule->rhs.end (); ++it) 443 | { 444 | if (! _M_grammar->isTerminal (*it)) 445 | continue; 446 | 447 | _M_current_rule->prec = *it; 448 | } 449 | } break; 450 | 451 | case 40: { 452 | Name tok = _M_grammar->intern (sym(2)); 453 | if (! _M_grammar->isTerminal (tok)) 454 | { 455 | qerr << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; 456 | _M_current_rule->prec = _M_grammar->names.end (); 457 | } 458 | else 459 | _M_current_rule->prec = tok; 460 | } break; 461 | 462 | case 42: { 463 | Name name = _M_grammar->intern (sym(2)); 464 | 465 | if (_M_grammar->terminals.find (name) == _M_grammar->terminals.end ()) 466 | _M_grammar->non_terminals.insert (name); 467 | 468 | _M_current_rule->rhs.push_back (name); 469 | } break; 470 | 471 | case 43: { 472 | sym(1) = QString(); 473 | } break; 474 | 475 | } // switch 476 | 477 | state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT); 478 | } 479 | 480 | else 481 | { 482 | break; 483 | } 484 | } 485 | 486 | qerr << _M_input_file << ":" << _M_line << ": Syntax error" << endl; 487 | return false; 488 | } 489 | 490 | -------------------------------------------------------------------------------- /examples/glsl/glsl.g: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- 3 | -- Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). 4 | -- Contact: http://www.qt-project.org/legal 5 | -- 6 | -- This file is part of the QtCore module of the Qt Toolkit. 7 | -- 8 | -- $QT_BEGIN_LICENSE:LGPL$ 9 | -- Commercial License Usage 10 | -- Licensees holding valid commercial Qt licenses may use this file in 11 | -- accordance with the commercial license agreement provided with the 12 | -- Software or, alternatively, in accordance with the terms contained in 13 | -- a written agreement between you and Digia. For licensing terms and 14 | -- conditions see http://qt.digia.com/licensing. For further information 15 | -- use the contact form at http://qt.digia.com/contact-us. 16 | -- 17 | -- GNU Lesser General Public License Usage 18 | -- Alternatively, this file may be used under the terms of the GNU Lesser 19 | -- General Public License version 2.1 as published by the Free Software 20 | -- Foundation and appearing in the file LICENSE.LGPL included in the 21 | -- packaging of this file. Please review the following information to 22 | -- ensure the GNU Lesser General Public License version 2.1 requirements 23 | -- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | -- 25 | -- In addition, as a special exception, Digia gives you certain additional 26 | -- rights. These rights are described in the Digia Qt LGPL Exception 27 | -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | -- 29 | -- GNU General Public License Usage 30 | -- Alternatively, this file may be used under the terms of the GNU 31 | -- General Public License version 3.0 as published by the Free Software 32 | -- Foundation and appearing in the file LICENSE.GPL included in the 33 | -- packaging of this file. Please review the following information to 34 | -- ensure the GNU General Public License version 3.0 requirements will be 35 | -- met: http://www.gnu.org/copyleft/gpl.html. 36 | -- 37 | -- 38 | -- $QT_END_LICENSE$ 39 | -- 40 | ---------------------------------------------------------------------------- 41 | 42 | %parser GLSLParserTable 43 | %merged_output glsl.cpp 44 | 45 | %token ADD_ASSIGN 46 | %token AMPERSAND 47 | %token AND_ASSIGN 48 | %token AND_OP 49 | %token ATTRIBUTE 50 | %token BANG 51 | %token BOOL 52 | %token BOOLCONSTANT 53 | %token BREAK 54 | %token BVEC2 55 | %token BVEC3 56 | %token BVEC4 57 | %token CARET 58 | %token COLON 59 | %token COMMA 60 | %token CONST 61 | %token CONTINUE 62 | %token DASH 63 | %token DEC_OP 64 | %token DISCARD 65 | %token DIV_ASSIGN 66 | %token DO 67 | %token DOT 68 | %token ELSE 69 | %token EQUAL 70 | %token EQ_OP 71 | %token FLOAT 72 | %token FLOATCONSTANT 73 | %token FOR 74 | %token GE_OP 75 | %token IDENTIFIER 76 | %token IF 77 | %token IN 78 | %token INC_OP 79 | %token INOUT 80 | %token INT 81 | %token INTCONSTANT 82 | %token IVEC2 83 | %token IVEC3 84 | %token IVEC4 85 | %token LEFT_ANGLE 86 | %token LEFT_ASSIGN 87 | %token LEFT_BRACE 88 | %token LEFT_BRACKET 89 | %token LEFT_OP 90 | %token LEFT_PAREN 91 | %token LE_OP 92 | %token MAT2 93 | %token MAT3 94 | %token MAT4 95 | %token MOD_ASSIGN 96 | %token MUL_ASSIGN 97 | %token NE_OP 98 | %token OR_ASSIGN 99 | %token OR_OP 100 | %token OUT 101 | %token PERCENT 102 | %token PLUS 103 | %token QUESTION 104 | %token RETURN 105 | %token RIGHT_ANGLE 106 | %token RIGHT_ASSIGN 107 | %token RIGHT_BRACE 108 | %token RIGHT_BRACKET 109 | %token RIGHT_OP 110 | %token RIGHT_PAREN 111 | %token SAMPLER1D 112 | %token SAMPLER1DSHADOW 113 | %token SAMPLER2D 114 | %token SAMPLER2DSHADOW 115 | %token SAMPLER3D 116 | %token SAMPLERCUBE 117 | %token SEMICOLON 118 | %token SLASH 119 | %token STAR 120 | %token STRUCT 121 | %token SUB_ASSIGN 122 | %token TILDE 123 | %token TYPE_NAME 124 | %token UNIFORM 125 | %token VARYING 126 | %token VEC2 127 | %token VEC3 128 | %token VEC4 129 | %token VERTICAL_BAR 130 | %token VOID 131 | %token WHILE 132 | %token XOR_ASSIGN 133 | %token XOR_OP 134 | %token ERROR 135 | %token HIGH_PRECISION 136 | %token MEDIUM_PRECISION 137 | %token LOW_PRECISION 138 | %start translation_unit 139 | 140 | 141 | /: 142 | 143 | #include 144 | 145 | class GLSLParser: protected $table 146 | { 147 | public: 148 | union Value { 149 | int i; 150 | unsigned u; 151 | unsigned long ul; 152 | unsigned long long ull; 153 | long l; 154 | double d; 155 | float f; 156 | const QString *s; 157 | // ### more... 158 | }; 159 | 160 | public: 161 | GLSLParser(); 162 | ~GLSLParser(); 163 | 164 | bool parse(); 165 | 166 | protected: 167 | inline void reallocateStack(); 168 | 169 | inline Value &sym(int index) 170 | { return sym_stack [tos + index - 1]; } 171 | 172 | int nextToken(); 173 | 174 | bool isTypename(const QString *s) const 175 | { 176 | return types.contains(s); 177 | } 178 | 179 | inline const QString *intern(const QString &s) 180 | { return &*string_repository.insert(s); } 181 | 182 | protected: 183 | int tos; 184 | int stack_size; 185 | Value *sym_stack; 186 | int *state_stack; 187 | Value yylval; 188 | QSet string_repository; 189 | QSet types; 190 | 191 | struct /*Context*/ { 192 | int line; 193 | const QString *function_name; 194 | QString fileName; 195 | 196 | void init() 197 | { 198 | line = 1; 199 | function_name = 0; 200 | fileName.clear(); 201 | } 202 | } context; 203 | }; 204 | 205 | inline void GLSLParser::reallocateStack() 206 | { 207 | if (! stack_size) 208 | stack_size = 128; 209 | else 210 | stack_size <<= 1; 211 | 212 | sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); 213 | state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); 214 | } 215 | 216 | :/ 217 | 218 | 219 | /. 220 | 221 | GLSLParser::GLSLParser(): 222 | tos(0), 223 | stack_size(0), 224 | sym_stack(0), 225 | state_stack(0) 226 | { 227 | } 228 | 229 | GLSLParser::~GLSLParser() 230 | { 231 | if (stack_size) { 232 | free(sym_stack); 233 | free(state_stack); 234 | } 235 | } 236 | 237 | bool GLSLParser::parse() 238 | { 239 | const int INITIAL_STATE = 0; 240 | 241 | int yytoken = -1; 242 | 243 | reallocateStack(); 244 | 245 | context.init(); 246 | tos = 0; 247 | state_stack[++tos] = INITIAL_STATE; 248 | 249 | while (true) 250 | { 251 | if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]]) 252 | yytoken = nextToken(); 253 | 254 | int act = t_action (state_stack [tos], yytoken); 255 | 256 | if (act == ACCEPT_STATE) { 257 | return true; 258 | } 259 | 260 | else if (act > 0) 261 | { 262 | if (++tos == stack_size) 263 | reallocateStack(); 264 | 265 | sym_stack [tos] = yylval; 266 | state_stack [tos] = act; 267 | yytoken = -1; 268 | } 269 | 270 | else if (act < 0) 271 | { 272 | int r = - act - 1; 273 | 274 | int ridx = rule_index [r]; 275 | printf ("*** reduce using rule %d %s ::=", r + 1, spell[rule_info [ridx]]); 276 | ++ridx; 277 | for (int i = ridx; i < ridx + rhs [r]; ++i) 278 | { 279 | int symbol = rule_info [i]; 280 | if (const char *name = spell [symbol]) 281 | printf (" %s", name); 282 | else 283 | printf (" #%d", symbol); 284 | } 285 | printf ("\n"); 286 | 287 | tos -= rhs [r]; 288 | act = state_stack [tos++]; 289 | 290 | switch (r) { 291 | ./ 292 | 293 | 294 | translation_unit ::= external_declaration ; 295 | translation_unit ::= translation_unit external_declaration ; 296 | 297 | variable_identifier ::= IDENTIFIER ; 298 | 299 | primary_expression ::= variable_identifier ; 300 | primary_expression ::= INTCONSTANT ; 301 | primary_expression ::= FLOATCONSTANT ; 302 | primary_expression ::= BOOLCONSTANT ; 303 | primary_expression ::= LEFT_PAREN expression RIGHT_PAREN ; 304 | 305 | 306 | postfix_expression ::= primary_expression ; 307 | postfix_expression ::= postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET ; 308 | postfix_expression ::= function_call ; 309 | postfix_expression ::= postfix_expression DOT IDENTIFIER ; 310 | postfix_expression ::= postfix_expression DOT TYPE_NAME ; 311 | postfix_expression ::= postfix_expression INC_OP ; 312 | postfix_expression ::= postfix_expression DEC_OP ; 313 | 314 | 315 | integer_expression ::= expression ; 316 | 317 | function_call ::= function_call_generic ; 318 | 319 | function_call_generic ::= function_call_header_with_parameters RIGHT_PAREN ; 320 | function_call_generic ::= function_call_header_no_parameters RIGHT_PAREN ; 321 | 322 | function_call_header_no_parameters ::= function_call_header VOID ; 323 | function_call_header_no_parameters ::= function_call_header ; 324 | 325 | 326 | function_call_header_with_parameters ::= function_call_header assignment_expression ; 327 | function_call_header_with_parameters ::= function_call_header_with_parameters COMMA assignment_expression ; 328 | 329 | function_call_header ::= function_identifier LEFT_PAREN ; 330 | 331 | function_identifier ::= constructor_identifier ; 332 | function_identifier ::= IDENTIFIER ; 333 | 334 | 335 | constructor_identifier ::= FLOAT ; 336 | constructor_identifier ::= INT ; 337 | constructor_identifier ::= BOOL ; 338 | constructor_identifier ::= VEC2 ; 339 | constructor_identifier ::= VEC3 ; 340 | constructor_identifier ::= VEC4 ; 341 | constructor_identifier ::= BVEC2 ; 342 | constructor_identifier ::= BVEC3 ; 343 | constructor_identifier ::= BVEC4 ; 344 | constructor_identifier ::= IVEC2 ; 345 | constructor_identifier ::= IVEC3 ; 346 | constructor_identifier ::= IVEC4 ; 347 | constructor_identifier ::= MAT2 ; 348 | constructor_identifier ::= MAT3 ; 349 | constructor_identifier ::= MAT4 ; 350 | constructor_identifier ::= TYPE_NAME ; 351 | 352 | unary_expression ::= postfix_expression ; 353 | unary_expression ::= INC_OP unary_expression ; 354 | unary_expression ::= DEC_OP unary_expression ; 355 | unary_expression ::= unary_operator unary_expression ; 356 | 357 | -- Grammar Note: No traditional style type casts. 358 | 359 | unary_operator ::= PLUS ; 360 | unary_operator ::= DASH ; 361 | unary_operator ::= BANG ; 362 | unary_operator ::= TILDE ; -- reserved 363 | 364 | -- Grammar Note: No '*' or '&' unary ops. Pointers are not supported. 365 | 366 | multiplicative_expression ::= unary_expression ; 367 | multiplicative_expression ::= multiplicative_expression STAR unary_expression ; 368 | multiplicative_expression ::= multiplicative_expression SLASH unary_expression ; 369 | multiplicative_expression ::= multiplicative_expression PERCENT unary_expression ; -- reserved 370 | 371 | 372 | additive_expression ::= multiplicative_expression ; 373 | additive_expression ::= additive_expression PLUS multiplicative_expression ; 374 | additive_expression ::= additive_expression DASH multiplicative_expression ; 375 | 376 | shift_expression ::= additive_expression ; 377 | shift_expression ::= shift_expression LEFT_OP additive_expression ; -- reserved 378 | shift_expression ::= shift_expression RIGHT_OP additive_expression ; -- reserved 379 | 380 | relational_expression ::= shift_expression ; 381 | relational_expression ::= relational_expression LEFT_ANGLE shift_expression ; 382 | relational_expression ::= relational_expression RIGHT_ANGLE shift_expression ; 383 | relational_expression ::= relational_expression LE_OP shift_expression ; 384 | relational_expression ::= relational_expression GE_OP shift_expression ; 385 | 386 | equality_expression ::= relational_expression ; 387 | equality_expression ::= equality_expression EQ_OP relational_expression ; 388 | equality_expression ::= equality_expression NE_OP relational_expression ; 389 | 390 | and_expression ::= equality_expression ; 391 | and_expression ::= and_expression AMPERSAND equality_expression ; -- reserved 392 | 393 | exclusive_or_expression ::= and_expression ; 394 | exclusive_or_expression ::= exclusive_or_expression CARET and_expression ; -- reserved 395 | 396 | inclusive_or_expression ::= exclusive_or_expression ; 397 | inclusive_or_expression ::= inclusive_or_expression VERTICAL_BAR exclusive_or_expression ; -- reserved 398 | 399 | logical_and_expression ::= inclusive_or_expression ; 400 | logical_and_expression ::= logical_and_expression AND_OP inclusive_or_expression ; 401 | 402 | logical_xor_expression ::= logical_and_expression ; 403 | logical_xor_expression ::= logical_xor_expression XOR_OP logical_and_expression ; 404 | 405 | logical_or_expression ::= logical_xor_expression ; 406 | logical_or_expression ::= logical_or_expression OR_OP logical_xor_expression ; 407 | 408 | conditional_expression ::= logical_or_expression ; 409 | conditional_expression ::= logical_or_expression QUESTION expression COLON conditional_expression ; 410 | 411 | assignment_expression ::= conditional_expression ; 412 | assignment_expression ::= unary_expression assignment_operator assignment_expression ; 413 | 414 | assignment_operator ::= EQUAL ; 415 | assignment_operator ::= MUL_ASSIGN ; 416 | assignment_operator ::= DIV_ASSIGN ; 417 | assignment_operator ::= MOD_ASSIGN ; -- reserved 418 | assignment_operator ::= ADD_ASSIGN ; 419 | assignment_operator ::= SUB_ASSIGN ; 420 | assignment_operator ::= LEFT_ASSIGN ; -- reserved 421 | assignment_operator ::= RIGHT_ASSIGN ; -- reserved 422 | assignment_operator ::= AND_ASSIGN ; -- reserved 423 | assignment_operator ::= XOR_ASSIGN ; -- reserved 424 | assignment_operator ::= OR_ASSIGN ; -- reserved 425 | 426 | expression ::= assignment_expression ; 427 | expression ::= expression COMMA assignment_expression ; 428 | 429 | constant_expression ::= conditional_expression ; 430 | 431 | declaration ::= function_prototype SEMICOLON ; 432 | declaration ::= init_declarator_list SEMICOLON ; 433 | 434 | function_prototype ::= function_declarator RIGHT_PAREN ; 435 | 436 | function_declarator ::= function_header ; 437 | function_declarator ::= function_header_with_parameters ; 438 | 439 | function_header_with_parameters ::= function_header parameter_declaration ; 440 | function_header_with_parameters ::= function_header_with_parameters COMMA parameter_declaration ; 441 | 442 | function_header ::= fully_specified_type IDENTIFIER LEFT_PAREN ; 443 | /. 444 | case $rule_number: { 445 | context.function_name = sym(2).s; 446 | } break; 447 | ./ 448 | 449 | parameter_declarator ::= type_specifier IDENTIFIER ; 450 | parameter_declarator ::= type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; 451 | 452 | parameter_declaration ::= type_qualifier parameter_qualifier parameter_declarator ; 453 | parameter_declaration ::= parameter_qualifier parameter_declarator ; 454 | parameter_declaration ::= type_qualifier parameter_qualifier parameter_type_specifier ; 455 | parameter_declaration ::= parameter_qualifier parameter_type_specifier ; 456 | 457 | parameter_qualifier ::= ; 458 | parameter_qualifier ::= IN ; 459 | parameter_qualifier ::= OUT ; 460 | parameter_qualifier ::= INOUT ; 461 | 462 | parameter_type_specifier ::= type_specifier ; 463 | parameter_type_specifier ::= type_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET ; 464 | 465 | init_declarator_list ::= single_declaration ; 466 | init_declarator_list ::= init_declarator_list COMMA IDENTIFIER ; 467 | init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ; 468 | init_declarator_list ::= init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression ; 469 | init_declarator_list ::= RIGHT_BRACKET ; 470 | init_declarator_list ::= init_declarator_list COMMA IDENTIFIER EQUAL initializer ; 471 | 472 | single_declaration ::= fully_specified_type ; 473 | single_declaration ::= fully_specified_type IDENTIFIER ; 474 | single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET ; 475 | single_declaration ::= fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; 476 | single_declaration ::= fully_specified_type IDENTIFIER EQUAL initializer ; 477 | 478 | -- Grammar Note: No 'enum', or 'typedef'. 479 | 480 | --fully_specified_type ::= type_specifier ; 481 | --fully_specified_type ::= type_qualifier type_specifier ; 482 | 483 | fully_specified_type ::= type_specifier ; 484 | fully_specified_type ::= type_qualifier ; 485 | fully_specified_type ::= fully_specified_type type_specifier ; 486 | fully_specified_type ::= fully_specified_type type_qualifier ; 487 | 488 | type_qualifier ::= CONST ; 489 | type_qualifier ::= ATTRIBUTE ; -- Vertex only. 490 | type_qualifier ::= VARYING ; 491 | type_qualifier ::= UNIFORM ; 492 | 493 | type_specifier ::= type_specifier_no_prec ; 494 | type_specifier ::= precision_qualifier type_specifier_no_prec ; 495 | 496 | type_specifier_no_prec ::= VOID ; 497 | type_specifier_no_prec ::= FLOAT ; 498 | type_specifier_no_prec ::= INT ; 499 | type_specifier_no_prec ::= BOOL ; 500 | type_specifier_no_prec ::= VEC2 ; 501 | type_specifier_no_prec ::= VEC3 ; 502 | type_specifier_no_prec ::= VEC4 ; 503 | type_specifier_no_prec ::= BVEC2 ; 504 | type_specifier_no_prec ::= BVEC3 ; 505 | type_specifier_no_prec ::= BVEC4 ; 506 | type_specifier_no_prec ::= IVEC2 ; 507 | type_specifier_no_prec ::= IVEC3 ; 508 | type_specifier_no_prec ::= IVEC4 ; 509 | type_specifier_no_prec ::= MAT2 ; 510 | type_specifier_no_prec ::= MAT3 ; 511 | type_specifier_no_prec ::= MAT4 ; 512 | type_specifier_no_prec ::= SAMPLER1D ; 513 | type_specifier_no_prec ::= SAMPLER2D ; 514 | type_specifier_no_prec ::= SAMPLER3D ; 515 | type_specifier_no_prec ::= SAMPLERCUBE ; 516 | type_specifier_no_prec ::= SAMPLER1DSHADOW ; 517 | type_specifier_no_prec ::= SAMPLER2DSHADOW ; 518 | type_specifier_no_prec ::= struct_specifier ; 519 | type_specifier_no_prec ::= TYPE_NAME ; 520 | 521 | precision_qualifier ::= HIGH_PRECISION ; 522 | precision_qualifier ::= MEDIUM_PRECISION ; 523 | precision_qualifier ::= LOW_PRECISION ; 524 | 525 | struct_specifier ::= STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE ; 526 | /. 527 | case $rule_number: { 528 | types.insert(sym(2).s); 529 | } break; 530 | ./ 531 | 532 | struct_specifier ::= STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE ; 533 | 534 | struct_declaration_list ::= struct_declaration ; 535 | struct_declaration_list ::= struct_declaration_list struct_declaration ; 536 | 537 | struct_declaration ::= type_specifier struct_declarator_list SEMICOLON ; 538 | 539 | struct_declarator_list ::= struct_declarator ; 540 | struct_declarator_list ::= struct_declarator_list COMMA struct_declarator ; 541 | 542 | struct_declarator ::= IDENTIFIER ; 543 | struct_declarator ::= IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET ; 544 | 545 | initializer ::= assignment_expression ; 546 | 547 | declaration_statement ::= declaration ; 548 | 549 | statement ::= compound_statement ; 550 | statement ::= simple_statement ; 551 | 552 | -- Grammar Note: No labeled statements; 'goto' is not supported. 553 | 554 | simple_statement ::= declaration_statement ; 555 | simple_statement ::= expression_statement ; 556 | simple_statement ::= selection_statement ; 557 | simple_statement ::= iteration_statement ; 558 | simple_statement ::= jump_statement ; 559 | 560 | compound_statement ::= LEFT_BRACE RIGHT_BRACE ; 561 | compound_statement ::= LEFT_BRACE statement_list RIGHT_BRACE ; 562 | 563 | statement_no_new_scope ::= compound_statement_no_new_scope ; 564 | statement_no_new_scope ::= simple_statement ; 565 | 566 | compound_statement_no_new_scope ::= LEFT_BRACE RIGHT_BRACE ; 567 | compound_statement_no_new_scope ::= LEFT_BRACE statement_list RIGHT_BRACE ; 568 | 569 | statement_list ::= statement ; 570 | statement_list ::= statement_list statement ; 571 | 572 | expression_statement ::= SEMICOLON ; 573 | expression_statement ::= expression SEMICOLON ; 574 | 575 | selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement ; 576 | selection_statement ::= IF LEFT_PAREN expression RIGHT_PAREN statement ; 577 | 578 | -- Grammar Note: No 'switch'. Switch statements not supported. 579 | 580 | condition ::= expression ; 581 | condition ::= fully_specified_type IDENTIFIER EQUAL initializer ; 582 | 583 | iteration_statement ::= WHILE LEFT_PAREN condition RIGHT_PAREN statement_no_new_scope ; 584 | iteration_statement ::= DO statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON ; 585 | iteration_statement ::= FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope ; 586 | 587 | for_init_statement ::= expression_statement ; 588 | for_init_statement ::= declaration_statement ; 589 | 590 | conditionopt ::= ; 591 | conditionopt ::= condition ; 592 | 593 | for_rest_statement ::= conditionopt SEMICOLON ; 594 | for_rest_statement ::= conditionopt SEMICOLON expression ; 595 | 596 | jump_statement ::= CONTINUE SEMICOLON ; 597 | jump_statement ::= BREAK SEMICOLON ; 598 | jump_statement ::= RETURN SEMICOLON ; 599 | jump_statement ::= RETURN expression SEMICOLON ; 600 | jump_statement ::= DISCARD SEMICOLON ; -- Fragment shader only. 601 | 602 | -- Grammar Note: No 'goto'. Gotos are not supported. 603 | 604 | external_declaration ::= function_definition ; 605 | external_declaration ::= declaration ; 606 | 607 | function_definition ::= function_prototype compound_statement_no_new_scope ; 608 | /. 609 | case $rule_number: { // $rule_name 610 | qDebug() << "--> function" << *context.function_name; 611 | } break; 612 | ./ 613 | 614 | 615 | 616 | 617 | 618 | /. 619 | } // switch 620 | 621 | state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT); 622 | } 623 | 624 | else 625 | { 626 | // ### ERROR RECOVERY HERE 627 | break; 628 | } 629 | } 630 | 631 | fprintf (stderr, "%s:%d: Syntax Error\n", qPrintable(context.fileName), context.line); 632 | 633 | return false; 634 | } 635 | 636 | #include "glsl-lex.incl" 637 | 638 | 639 | ///////////////////////////// 640 | // entry point 641 | ///////////////////////////// 642 | int main() 643 | { 644 | #if 0 // dump the GLSL grammar 645 | for (int r = 0; r < GLSLParserTable::RULE_COUNT; ++r) 646 | { 647 | int ridx = GLSLParserTable::rule_index [r]; 648 | int rhs = GLSLParserTable::rhs [r]; 649 | printf ("%3d) %s ::=", r + 1, GLSLParserTable::spell[GLSLParserTable::rule_info [ridx]]); 650 | ++ridx; 651 | for (int i = ridx; i < ridx + rhs; ++i) 652 | { 653 | int symbol = GLSLParserTable::rule_info [i]; 654 | if (const char *name = GLSLParserTable::spell [symbol]) 655 | printf (" %s", name); 656 | else 657 | printf (" #%d", symbol); 658 | } 659 | printf ("\n"); 660 | } 661 | #endif 662 | 663 | GLSLParser parser; 664 | 665 | if (parser.parse()) 666 | qDebug() << "OK"; 667 | else 668 | qDebug() << "KO"; 669 | } 670 | 671 | ./ 672 | -------------------------------------------------------------------------------- /src/lalr.g: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- 3 | -- Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | -- Contact: http://www.qt-project.org/legal 5 | -- 6 | -- This file is part of the QLALR project on Qt Labs. 7 | -- 8 | -- $QT_BEGIN_LICENSE:LGPL$ 9 | -- Commercial License Usage 10 | -- Licensees holding valid commercial Qt licenses may use this file in 11 | -- accordance with the commercial license agreement provided with the 12 | -- Software or, alternatively, in accordance with the terms contained in 13 | -- a written agreement between you and Digia. For licensing terms and 14 | -- conditions see http://qt.digia.com/licensing. For further information 15 | -- use the contact form at http://qt.digia.com/contact-us. 16 | -- 17 | -- GNU Lesser General Public License Usage 18 | -- Alternatively, this file may be used under the terms of the GNU Lesser 19 | -- General Public License version 2.1 as published by the Free Software 20 | -- Foundation and appearing in the file LICENSE.LGPL included in the 21 | -- packaging of this file. Please review the following information to 22 | -- ensure the GNU Lesser General Public License version 2.1 requirements 23 | -- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | -- 25 | -- In addition, as a special exception, Digia gives you certain additional 26 | -- rights. These rights are described in the Digia Qt LGPL Exception 27 | -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | -- 29 | -- GNU General Public License Usage 30 | -- Alternatively, this file may be used under the terms of the GNU 31 | -- General Public License version 3.0 as published by the Free Software 32 | -- Foundation and appearing in the file LICENSE.GPL included in the 33 | -- packaging of this file. Please review the following information to 34 | -- ensure the GNU General Public License version 3.0 requirements will be 35 | -- met: http://www.gnu.org/copyleft/gpl.html. 36 | -- 37 | -- 38 | -- $QT_END_LICENSE$ 39 | -- 40 | ----------------------------------------------------------------------------- 41 | 42 | 43 | %parser grammar 44 | 45 | %decl recognizer.h 46 | %impl recognizer.cpp 47 | 48 | %token ID "identifier" 49 | %token STRING_LITERAL "string literal" 50 | 51 | %token DECL_FILE "%decl" 52 | %token EXPECT "%expect" 53 | %token EXPECT_RR "%expect-lr" 54 | %token IMPL_FILE "%impl" 55 | %token LEFT "%left" 56 | %token MERGED_OUTPUT "%merged_output" 57 | %token NONASSOC "%nonassoc" 58 | %token PARSER "%parser" 59 | %token PREC "%prec" 60 | %token RIGHT "%right" 61 | %token START "%start" 62 | %token TOKEN "%token" 63 | %token TOKEN_PREFIX "%token_prefix" 64 | 65 | %token COLON ":" 66 | %token OR "|" 67 | %token SEMICOLON ";" 68 | 69 | %token DECL 70 | %token IMPL 71 | 72 | %token ERROR 73 | 74 | %start Specification 75 | 76 | 77 | /: 78 | /**************************************************************************** 79 | ** 80 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 81 | ** Contact: http://www.qt-project.org/legal 82 | ** 83 | ** This file is part of the QLALR project on Qt Labs. 84 | ** 85 | ** $QT_BEGIN_LICENSE:LGPL$ 86 | ** Commercial License Usage 87 | ** Licensees holding valid commercial Qt licenses may use this file in 88 | ** accordance with the commercial license agreement provided with the 89 | ** Software or, alternatively, in accordance with the terms contained in 90 | ** a written agreement between you and Digia. For licensing terms and 91 | ** conditions see http://qt.digia.com/licensing. For further information 92 | ** use the contact form at http://qt.digia.com/contact-us. 93 | ** 94 | ** GNU Lesser General Public License Usage 95 | ** Alternatively, this file may be used under the terms of the GNU Lesser 96 | ** General Public License version 2.1 as published by the Free Software 97 | ** Foundation and appearing in the file LICENSE.LGPL included in the 98 | ** packaging of this file. Please review the following information to 99 | ** ensure the GNU Lesser General Public License version 2.1 requirements 100 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 101 | ** 102 | ** In addition, as a special exception, Digia gives you certain additional 103 | ** rights. These rights are described in the Digia Qt LGPL Exception 104 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 105 | ** 106 | ** GNU General Public License Usage 107 | ** Alternatively, this file may be used under the terms of the GNU 108 | ** General Public License version 3.0 as published by the Free Software 109 | ** Foundation and appearing in the file LICENSE.GPL included in the 110 | ** packaging of this file. Please review the following information to 111 | ** ensure the GNU General Public License version 3.0 requirements will be 112 | ** met: http://www.gnu.org/copyleft/gpl.html. 113 | ** 114 | ** 115 | ** $QT_END_LICENSE$ 116 | ** 117 | ****************************************************************************/ 118 | 119 | #include 120 | #include 121 | #include 122 | #include 123 | 124 | #include "$header" 125 | #include "lalr.h" 126 | 127 | #include 128 | 129 | class Recognizer: protected $table 130 | { 131 | public: 132 | Recognizer (Grammar *grammar, bool no_lines); 133 | ~Recognizer(); 134 | 135 | bool parse (const QString &input_file = QString ()); 136 | 137 | inline QString decls () const { return _M_decls; } 138 | inline QString impls () const { return _M_impls; } 139 | 140 | protected: 141 | inline void reallocateStack (); 142 | 143 | inline QString &sym (int index) 144 | { return sym_stack [tos + index - 1]; } 145 | 146 | protected: // scanner 147 | int nextToken(); 148 | 149 | inline void inp () 150 | { 151 | if (_M_currentChar != _M_lastChar) 152 | { 153 | ch = *_M_currentChar++; 154 | 155 | if (ch == QLatin1Char('\n')) 156 | ++_M_line; 157 | } 158 | else 159 | ch = QChar(); 160 | } 161 | 162 | QString expand (const QString &text) const; 163 | 164 | protected: 165 | // recognizer 166 | int tos; 167 | int stack_size; 168 | QVector sym_stack; 169 | int *state_stack; 170 | 171 | QString _M_contents; 172 | QString::const_iterator _M_firstChar; 173 | QString::const_iterator _M_lastChar; 174 | QString::const_iterator _M_currentChar; 175 | 176 | // scanner 177 | QChar ch; 178 | int _M_line; 179 | int _M_action_line; 180 | Grammar *_M_grammar; 181 | RulePointer _M_current_rule; 182 | QString _M_input_file; 183 | 184 | QString _M_decls; 185 | QString _M_impls; 186 | QString _M_current_value; 187 | bool _M_no_lines; 188 | }; 189 | :/ 190 | 191 | /. 192 | /**************************************************************************** 193 | ** 194 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 195 | ** Contact: http://www.qt-project.org/legal 196 | ** 197 | ** This file is part of the QLALR project on Qt Labs. 198 | ** 199 | ** $QT_BEGIN_LICENSE:LGPL$ 200 | ** Commercial License Usage 201 | ** Licensees holding valid commercial Qt licenses may use this file in 202 | ** accordance with the commercial license agreement provided with the 203 | ** Software or, alternatively, in accordance with the terms contained in 204 | ** a written agreement between you and Digia. For licensing terms and 205 | ** conditions see http://qt.digia.com/licensing. For further information 206 | ** use the contact form at http://qt.digia.com/contact-us. 207 | ** 208 | ** GNU Lesser General Public License Usage 209 | ** Alternatively, this file may be used under the terms of the GNU Lesser 210 | ** General Public License version 2.1 as published by the Free Software 211 | ** Foundation and appearing in the file LICENSE.LGPL included in the 212 | ** packaging of this file. Please review the following information to 213 | ** ensure the GNU Lesser General Public License version 2.1 requirements 214 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 215 | ** 216 | ** In addition, as a special exception, Digia gives you certain additional 217 | ** rights. These rights are described in the Digia Qt LGPL Exception 218 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 219 | ** 220 | ** GNU General Public License Usage 221 | ** Alternatively, this file may be used under the terms of the GNU 222 | ** General Public License version 3.0 as published by the Free Software 223 | ** Foundation and appearing in the file LICENSE.GPL included in the 224 | ** packaging of this file. Please review the following information to 225 | ** ensure the GNU General Public License version 3.0 requirements will be 226 | ** met: http://www.gnu.org/copyleft/gpl.html. 227 | ** 228 | ** 229 | ** $QT_END_LICENSE$ 230 | ** 231 | ****************************************************************************/ 232 | 233 | #include "recognizer.h" 234 | #include 235 | #include 236 | #include 237 | 238 | Recognizer::Recognizer (Grammar *grammar, bool no_lines): 239 | tos(0), 240 | stack_size(0), 241 | state_stack(0), 242 | _M_line(1), 243 | _M_action_line(0), 244 | _M_grammar(grammar), 245 | _M_no_lines(no_lines) 246 | { 247 | } 248 | 249 | Recognizer::~Recognizer() 250 | { 251 | if (stack_size) 252 | ::free(state_stack); 253 | } 254 | 255 | inline void Recognizer::reallocateStack() 256 | { 257 | if (! stack_size) 258 | stack_size = 128; 259 | else 260 | stack_size <<= 1; 261 | 262 | sym_stack.resize (stack_size); 263 | 264 | if (! state_stack) 265 | state_stack = reinterpret_cast (::malloc(stack_size * sizeof(int))); 266 | else 267 | state_stack = reinterpret_cast (::realloc(state_stack, stack_size * sizeof(int))); 268 | } 269 | 270 | int Recognizer::nextToken() 271 | { 272 | QString text; 273 | 274 | Lagain: 275 | while (ch.isSpace ()) 276 | inp (); 277 | 278 | if (ch.isNull ()) 279 | return EOF_SYMBOL; 280 | 281 | int token = ch.unicode (); 282 | 283 | if (token == '"') 284 | { 285 | inp(); // skip " 286 | text.clear (); 287 | while (! ch.isNull () && ch != QLatin1Char ('"')) 288 | { 289 | if (ch == QLatin1Char ('\\')) 290 | { 291 | text += ch; 292 | inp(); 293 | } 294 | text += ch; 295 | inp (); 296 | } 297 | 298 | if (ch == QLatin1Char ('"')) 299 | inp (); 300 | else 301 | qerr << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; 302 | 303 | _M_current_value = text; 304 | return (token = STRING_LITERAL); 305 | } 306 | 307 | else if (ch.isLetterOrNumber () || ch == QLatin1Char ('_')) 308 | { 309 | text.clear (); 310 | do { text += ch; inp (); } 311 | while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('.')); 312 | _M_current_value = text; 313 | return (token = ID); 314 | } 315 | 316 | else if (token == '%') 317 | { 318 | text.clear (); 319 | 320 | do { inp (); } 321 | while (ch.isSpace ()); 322 | 323 | do { text += ch; inp (); } 324 | while (ch.isLetterOrNumber () || ch == QLatin1Char ('_') || ch == QLatin1Char ('-')); 325 | 326 | if (text == QLatin1String("token_prefix")) 327 | return (token = TOKEN_PREFIX); 328 | else if (text == QLatin1String("merged_output")) 329 | return (token = MERGED_OUTPUT); 330 | else if (text == QLatin1String("token")) 331 | return (token = TOKEN); 332 | else if (text == QLatin1String("start")) 333 | return (token = START); 334 | else if (text == QLatin1String("parser")) 335 | return (token = PARSER); 336 | else if (text == QLatin1String("decl")) 337 | return (token = DECL_FILE); 338 | else if (text == QLatin1String("impl")) 339 | return (token = IMPL_FILE); 340 | else if (text == QLatin1String("expect")) 341 | return (token = EXPECT); 342 | else if (text == QLatin1String("expect-rr")) 343 | return (token = EXPECT_RR); 344 | else if (text == QLatin1String("left")) 345 | return (token = LEFT); 346 | else if (text == QLatin1String("right")) 347 | return (token = RIGHT); 348 | else if (text == QLatin1String("nonassoc")) 349 | return (token = NONASSOC); 350 | else if (text == QLatin1String("prec")) 351 | return (token = PREC); 352 | else 353 | { 354 | qerr << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; 355 | exit (EXIT_FAILURE); 356 | return (token = ERROR); 357 | } 358 | } 359 | 360 | inp (); 361 | 362 | if (token == '-' && ch == QLatin1Char ('-')) 363 | { 364 | do { inp (); } 365 | while (! ch.isNull () && ch != QLatin1Char ('\n')); 366 | goto Lagain; 367 | } 368 | 369 | else if (token == ':' && ch == QLatin1Char (':')) 370 | { 371 | inp (); 372 | if (ch != QLatin1Char ('=')) 373 | return (token = ERROR); 374 | inp (); 375 | return (token = COLON); 376 | } 377 | 378 | else if (token == '/' && ch == QLatin1Char (':')) 379 | { 380 | _M_action_line = _M_line; 381 | 382 | text.clear (); 383 | if (! _M_no_lines) 384 | text += QLatin1String ("\n#line ") + QString::number (_M_action_line) + " \"" + _M_input_file + "\"\n"; 385 | inp (); // skip ':' 386 | 387 | forever 388 | { 389 | while (! ch.isNull ()) 390 | { 391 | token = ch.unicode (); 392 | inp (); 393 | 394 | if (token == ':' && ch == QLatin1Char ('/')) 395 | break; 396 | 397 | text += QLatin1Char (token); 398 | } 399 | 400 | if (ch != QLatin1Char ('/')) 401 | return (token = ERROR); 402 | 403 | inp (); 404 | 405 | if (ch.isNull () || ch.isSpace ()) 406 | { 407 | _M_current_value = text; 408 | return (token = DECL); 409 | } 410 | else 411 | text += QLatin1String (":/"); 412 | } 413 | } 414 | 415 | else if (token == '/' && ch == QLatin1Char ('.')) 416 | { 417 | _M_action_line = _M_line; 418 | 419 | text.clear (); 420 | if (! _M_no_lines) 421 | text += QLatin1String ("\n#line ") + QString::number (_M_action_line) + " \"" + _M_input_file + "\"\n"; 422 | 423 | inp (); // skip ':' 424 | 425 | forever 426 | { 427 | while (! ch.isNull ()) 428 | { 429 | token = ch.unicode (); 430 | inp (); 431 | 432 | if (token == '.' && ch == QLatin1Char ('/')) 433 | break; 434 | 435 | text += QLatin1Char (token); 436 | } 437 | 438 | if (ch != QLatin1Char ('/')) 439 | return (token = ERROR); 440 | 441 | inp (); 442 | 443 | if (ch.isNull () || ch.isSpace ()) 444 | { 445 | _M_current_value = text; 446 | return (token = IMPL); 447 | } 448 | else 449 | text += QLatin1String ("./"); 450 | } 451 | } 452 | 453 | switch (token) { 454 | case ':': 455 | return (token = COLON); 456 | 457 | case ';': 458 | return (token = SEMICOLON); 459 | 460 | case '|': 461 | return (token = OR); 462 | 463 | default: 464 | break; 465 | } 466 | 467 | return token; 468 | } 469 | 470 | bool Recognizer::parse (const QString &input_file) 471 | { 472 | _M_input_file = input_file; 473 | 474 | QFile file(_M_input_file); 475 | if (! file.open(QFile::ReadOnly)) 476 | { 477 | qerr << "qlalr: no input file\n"; 478 | return false; 479 | } 480 | 481 | QString _M_contents = QTextStream(&file).readAll(); 482 | _M_firstChar = _M_contents.constBegin(); 483 | _M_lastChar = _M_contents.constEnd(); 484 | _M_currentChar = _M_firstChar; 485 | _M_line = 1; 486 | 487 | int yytoken = -1; 488 | inp (); 489 | 490 | reallocateStack(); 491 | 492 | _M_current_rule = _M_grammar->rules.end (); 493 | _M_decls.clear (); 494 | _M_impls.clear (); 495 | 496 | tos = 0; 497 | state_stack[++tos] = 0; 498 | 499 | while (true) 500 | { 501 | if (yytoken == -1 && - TERMINAL_COUNT != action_index [state_stack [tos]]) 502 | yytoken = nextToken(); 503 | 504 | int act = t_action (state_stack [tos], yytoken); 505 | 506 | if (act == ACCEPT_STATE) 507 | return true; 508 | 509 | else if (act > 0) 510 | { 511 | if (++tos == stack_size) 512 | reallocateStack(); 513 | 514 | sym_stack [tos] = _M_current_value; 515 | state_stack [tos] = act; 516 | yytoken = -1; 517 | } 518 | 519 | else if (act < 0) 520 | { 521 | int r = - act - 1; 522 | 523 | tos -= rhs [r]; 524 | act = state_stack [tos++]; 525 | 526 | switch (r) { 527 | ./ 528 | 529 | ----------------------------------------------------------- SPECS 530 | Specification ::= Options Tokens Start Rules ; 531 | 532 | Options ::= Empty ; 533 | Options ::= Options Option ; 534 | 535 | StartHeader ::= START ID ; 536 | /. 537 | case $rule_number: { 538 | Name name = _M_grammar->intern (sym(2)); 539 | _M_grammar->start = name; 540 | _M_grammar->non_terminals.insert (name); 541 | } break; 542 | ./ 543 | 544 | Start ::= StartHeader UserActionOpt ; 545 | 546 | ----------------------------------------------------------- OPTIONS 547 | Option ::= PARSER ID ; 548 | /. 549 | case $rule_number: { 550 | _M_grammar->table_name = sym(2); 551 | } break; 552 | ./ 553 | 554 | Option ::= MERGED_OUTPUT ID ; 555 | /. 556 | case $rule_number: { 557 | _M_grammar->merged_output = sym(2); 558 | } break; 559 | ./ 560 | 561 | Option ::= DECL_FILE ID ; 562 | /. 563 | case $rule_number: { 564 | _M_grammar->decl_file_name = sym(2); 565 | } break; 566 | ./ 567 | 568 | 569 | Option ::= IMPL_FILE ID ; 570 | /. 571 | case $rule_number: { 572 | _M_grammar->impl_file_name = sym(2); 573 | } break; 574 | ./ 575 | 576 | Option ::= EXPECT ID ; 577 | /. 578 | case $rule_number: { 579 | _M_grammar->expected_shift_reduce = sym(2).toInt(); 580 | } break; 581 | ./ 582 | 583 | Option ::= EXPECT_RR ID ; 584 | /. 585 | case $rule_number: { 586 | _M_grammar->expected_reduce_reduce = sym(2).toInt(); 587 | } break; 588 | ./ 589 | 590 | 591 | Option ::= TOKEN_PREFIX ID ; 592 | /. 593 | case $rule_number: { 594 | _M_grammar->token_prefix = sym(2); 595 | } break; 596 | ./ 597 | 598 | 599 | ----------------------------------------------------------- TOKENS 600 | Tokens ::= Empty ; 601 | Tokens ::= Tokens Token ; 602 | 603 | Token ::= TOKEN TerminalList ; 604 | 605 | TerminalList ::= Terminal ; 606 | 607 | TerminalList ::= TerminalList Terminal ; 608 | 609 | Terminal ::= ID Empty ; 610 | /.case $rule_number:./ 611 | 612 | Terminal ::= ID STRING_LITERAL ; 613 | /.case $rule_number: { 614 | Name name = _M_grammar->intern (sym(1)); 615 | _M_grammar->terminals.insert (name); 616 | _M_grammar->spells.insert (name, sym(2)); 617 | } break; 618 | ./ 619 | 620 | PrecHeader: LEFT ; 621 | /. 622 | case $rule_number: { 623 | _M_grammar->current_assoc = Grammar::Left; 624 | ++_M_grammar->current_prec; 625 | } break; 626 | ./ 627 | 628 | PrecHeader: RIGHT ; 629 | /. 630 | case $rule_number: { 631 | _M_grammar->current_assoc = Grammar::Right; 632 | ++_M_grammar->current_prec; 633 | } break; 634 | ./ 635 | 636 | PrecHeader: NONASSOC ; 637 | /. 638 | case $rule_number: { 639 | _M_grammar->current_assoc = Grammar::NonAssoc; 640 | ++_M_grammar->current_prec; 641 | } break; 642 | ./ 643 | 644 | Token ::= PrecHeader TokenList ; 645 | 646 | TokenList ::= TokenId ; 647 | TokenList ::= TokenList TokenId ; 648 | 649 | TokenId ::= ID ; 650 | /. 651 | case $rule_number: { 652 | Name name = _M_grammar->intern (sym(1)); 653 | _M_grammar->terminals.insert (name); 654 | 655 | Grammar::TokenInfo info; 656 | info.prec = _M_grammar->current_prec; 657 | info.assoc = _M_grammar->current_assoc; 658 | _M_grammar->token_info.insert (name, info); 659 | } break; 660 | ./ 661 | 662 | ----------------------------------------------------------- Code 663 | Code ::= DECL ; 664 | /. 665 | case $rule_number: { 666 | _M_decls += expand (sym(1)); 667 | } break; 668 | ./ 669 | 670 | 671 | Code ::= IMPL ; 672 | /. 673 | case $rule_number: { 674 | _M_impls += expand (sym(1)); 675 | } break; 676 | ./ 677 | 678 | UserAction ::= Code ; 679 | UserAction ::= UserAction Code ; 680 | 681 | UserActionOpt ::= ; 682 | UserActionOpt ::= UserAction ; 683 | 684 | ----------------------------------------------------------- RULES 685 | Rules ::= Empty ; 686 | Rules ::= Rules Rule ; 687 | 688 | RuleHeader ::= ID COLON ; 689 | /. 690 | case $rule_number: { 691 | _M_current_rule = _M_grammar->rules.insert (_M_grammar->rules.end (), Rule ()); 692 | _M_current_rule->lhs = _M_grammar->intern (sym(1)); 693 | _M_grammar->declared_lhs.insert (_M_current_rule->lhs); 694 | 695 | if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) 696 | { 697 | qerr << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; 698 | return false; 699 | } 700 | 701 | _M_grammar->non_terminals.insert (_M_current_rule->lhs); 702 | } break; 703 | ./ 704 | 705 | 706 | Rule ::= RuleHeader RuleDefinition SEMICOLON UserActionOpt ; 707 | 708 | RuleDefinition ::= Symbols PrecOpt UserActionOpt ; 709 | RuleDefinition ::= RuleDefinition NewRule OR Symbols PrecOpt UserActionOpt ; 710 | 711 | NewRule ::= ; 712 | /. 713 | case $rule_number: { 714 | Name lhs = _M_current_rule->lhs; 715 | _M_current_rule = _M_grammar->rules.insert (_M_grammar->rules.end (), Rule ()); 716 | _M_current_rule->lhs = lhs; 717 | _M_grammar->declared_lhs.insert (_M_current_rule->lhs); 718 | 719 | if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) 720 | { 721 | qerr << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; 722 | return false; 723 | } 724 | 725 | _M_grammar->non_terminals.insert (_M_current_rule->lhs); 726 | } break; 727 | ./ 728 | 729 | PrecOpt ::= ; 730 | /. 731 | case $rule_number: { 732 | _M_current_rule->prec = _M_grammar->names.end (); 733 | 734 | for (NameList::iterator it = _M_current_rule->rhs.begin (); it != _M_current_rule->rhs.end (); ++it) 735 | { 736 | if (! _M_grammar->isTerminal (*it)) 737 | continue; 738 | 739 | _M_current_rule->prec = *it; 740 | } 741 | } break; 742 | ./ 743 | 744 | PrecOpt ::= PREC ID ; 745 | /. 746 | case $rule_number: { 747 | Name tok = _M_grammar->intern (sym(2)); 748 | if (! _M_grammar->isTerminal (tok)) 749 | { 750 | qerr << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; 751 | _M_current_rule->prec = _M_grammar->names.end (); 752 | } 753 | else 754 | _M_current_rule->prec = tok; 755 | } break; 756 | ./ 757 | 758 | ----------------------------------------------------------- SYMBOLS 759 | Symbols ::= Empty ; 760 | Symbols ::= Symbols ID ; 761 | /. 762 | case $rule_number: { 763 | Name name = _M_grammar->intern (sym(2)); 764 | 765 | if (_M_grammar->terminals.find (name) == _M_grammar->terminals.end ()) 766 | _M_grammar->non_terminals.insert (name); 767 | 768 | _M_current_rule->rhs.push_back (name); 769 | } break; 770 | ./ 771 | 772 | ----------------------------------------------------------- HELPERS 773 | Empty ::= ; 774 | /. 775 | case $rule_number: { 776 | sym(1) = QString(); 777 | } break; 778 | ./ 779 | 780 | 781 | 782 | 783 | ----------------------------------------------------------- END 784 | /. 785 | } // switch 786 | 787 | state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT); 788 | } 789 | 790 | else 791 | { 792 | break; 793 | } 794 | } 795 | 796 | qerr << _M_input_file << ":" << _M_line << ": Syntax error" << endl; 797 | return false; 798 | } 799 | 800 | ./ 801 | -------------------------------------------------------------------------------- /src/lalr.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the utils of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:LGPL$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and Digia. For licensing terms and 14 | ** conditions see http://qt.digia.com/licensing. For further information 15 | ** use the contact form at http://qt.digia.com/contact-us. 16 | ** 17 | ** GNU Lesser General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser 19 | ** General Public License version 2.1 as published by the Free Software 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the 21 | ** packaging of this file. Please review the following information to 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 | ** 25 | ** In addition, as a special exception, Digia gives you certain additional 26 | ** rights. These rights are described in the Digia Qt LGPL Exception 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 28 | ** 29 | ** GNU General Public License Usage 30 | ** Alternatively, this file may be used under the terms of the GNU 31 | ** General Public License version 3.0 as published by the Free Software 32 | ** Foundation and appearing in the file LICENSE.GPL included in the 33 | ** packaging of this file. Please review the following information to 34 | ** ensure the GNU General Public License version 3.0 requirements will be 35 | ** met: http://www.gnu.org/copyleft/gpl.html. 36 | ** 37 | ** 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | 43 | #include "lalr.h" 44 | #include 45 | 46 | #include 47 | 48 | #define QLALR_NO_DEBUG_NULLABLES 49 | #define QLALR_NO_DEBUG_LOOKBACKS 50 | #define QLALR_NO_DEBUG_DIRECT_READS 51 | #define QLALR_NO_DEBUG_READS 52 | #define QLALR_NO_DEBUG_INCLUDES 53 | #define QLALR_NO_DEBUG_LOOKAHEADS 54 | 55 | QT_BEGIN_NAMESPACE 56 | QTextStream qerr (stderr, QIODevice::WriteOnly); 57 | QTextStream qout (stdout, QIODevice::WriteOnly); 58 | 59 | bool operator < (Name a, Name b) 60 | { 61 | return *a < *b; 62 | } 63 | 64 | bool operator < (ItemPointer a, ItemPointer b) 65 | { 66 | return &*a < &*b; 67 | } 68 | 69 | bool operator < (StatePointer a, StatePointer b) 70 | { 71 | return &*a < &*b; 72 | } 73 | QT_END_NAMESPACE 74 | 75 | bool Read::operator < (const Read &other) const 76 | { 77 | if (state == other.state) 78 | return nt < other.nt; 79 | 80 | return state < other.state; 81 | } 82 | 83 | bool Include::operator < (const Include &other) const 84 | { 85 | if (state == other.state) 86 | return nt < other.nt; 87 | 88 | return state < other.state; 89 | } 90 | 91 | bool Lookback::operator < (const Lookback &other) const 92 | { 93 | if (state == other.state) 94 | return nt < other.nt; 95 | 96 | return state < other.state; 97 | } 98 | 99 | QTextStream &operator << (QTextStream &out, const Name &n) 100 | { 101 | return out << *n; 102 | } 103 | 104 | QTextStream &operator << (QTextStream &out, const Rule &r) 105 | { 106 | out << *r.lhs << " ::="; 107 | 108 | for (NameList::const_iterator name = r.rhs.begin (); name != r.rhs.end (); ++name) 109 | out << " " << **name; 110 | 111 | return out; 112 | } 113 | 114 | QTextStream &operator << (QTextStream &out, const NameSet &ns) 115 | { 116 | out << "{"; 117 | 118 | for (NameSet::const_iterator n = ns.begin (); n != ns.end (); ++n) 119 | { 120 | if (n != ns.begin ()) 121 | out << ", "; 122 | 123 | out << *n; 124 | } 125 | 126 | return out << "}"; 127 | } 128 | 129 | Item Item::next () const 130 | { 131 | Q_ASSERT (! isReduceItem ()); 132 | 133 | Item n; 134 | n.rule = rule; 135 | n.dot = dot; 136 | ++n.dot; 137 | 138 | return n; 139 | } 140 | 141 | QTextStream &operator << (QTextStream &out, const Item &item) 142 | { 143 | RulePointer r = item.rule; 144 | 145 | out << *r->lhs << ":"; 146 | for (NameList::iterator name = r->rhs.begin (); name != r->rhs.end (); ++name) 147 | { 148 | out << " "; 149 | 150 | if (item.dot == name) 151 | out << ". "; 152 | 153 | out << **name; 154 | } 155 | 156 | if (item.isReduceItem ()) 157 | out << " ."; 158 | 159 | return out; 160 | } 161 | 162 | State::State (Grammar *g): 163 | defaultReduce (g->rules.end ()) 164 | { 165 | } 166 | 167 | QPair State::insert (const Item &item) 168 | { 169 | ItemPointer it = qFind (kernel.begin (), kernel.end (), item); 170 | 171 | if (it != kernel.end ()) 172 | return qMakePair (it, false); 173 | 174 | return qMakePair (kernel.insert (it, item), true); 175 | } 176 | 177 | QPair State::insertClosure (const Item &item) 178 | { 179 | ItemPointer it = qFind (closure.begin (), closure.end (), item); 180 | 181 | if (it != closure.end ()) 182 | return qMakePair (it, false); 183 | 184 | return qMakePair (closure.insert (it, item), true); 185 | } 186 | 187 | 188 | ///////////////////////////////////////////////////////////// 189 | // Grammar 190 | ///////////////////////////////////////////////////////////// 191 | Grammar::Grammar (): 192 | start (names.end ()) 193 | { 194 | expected_shift_reduce = 0; 195 | expected_reduce_reduce = 0; 196 | current_prec = 0; 197 | current_assoc = NonAssoc; 198 | 199 | table_name = QLatin1String ("parser_table"); 200 | 201 | tk_end = intern ("$end"); 202 | terminals.insert (tk_end); 203 | spells.insert (tk_end, "end of file"); 204 | 205 | /*tk_error= terminals.insert (intern ("error"))*/; 206 | } 207 | 208 | Name Grammar::intern (const QString &id) 209 | { 210 | Name name = qFind (names.begin (), names.end (), id); 211 | 212 | if (name == names.end ()) 213 | name = names.insert (names.end (), id); 214 | 215 | return name; 216 | } 217 | 218 | void Grammar::buildRuleMap () 219 | { 220 | NameSet undefined; 221 | for (RulePointer rule = rules.begin (); rule != rules.end (); ++rule) 222 | { 223 | for (NameList::iterator it = rule->rhs.begin (); it != rule->rhs.end (); ++it) 224 | { 225 | Name name = *it; 226 | if (isTerminal (name) || declared_lhs.find (name) != declared_lhs.end () 227 | || undefined.find (name) != undefined.end ()) 228 | continue; 229 | 230 | undefined.insert(name); 231 | fprintf (stderr, "*** Warning. Symbol `%s' is not defined\n", qPrintable (*name)); 232 | } 233 | 234 | rule_map.insert (rule->lhs, rule); 235 | } 236 | } 237 | 238 | void Grammar::buildExtendedGrammar () 239 | { 240 | accept_symbol = intern ("$accept"); 241 | goal = rules.insert (rules.end (), Rule ()); 242 | goal->lhs = accept_symbol; 243 | goal->rhs.push_back (start); 244 | goal->rhs.push_back (tk_end); 245 | 246 | non_terminals.insert (accept_symbol); 247 | } 248 | 249 | struct _Nullable: public std::unary_function 250 | { 251 | Automaton *_M_automaton; 252 | 253 | _Nullable (Automaton *aut): 254 | _M_automaton (aut) {} 255 | 256 | bool operator () (Name name) const 257 | { return _M_automaton->nullables.find (name) != _M_automaton->nullables.end (); } 258 | }; 259 | 260 | Automaton::Automaton (Grammar *g): 261 | _M_grammar (g), 262 | start (states.end ()) 263 | { 264 | } 265 | 266 | int Automaton::id (RulePointer rule) 267 | { 268 | return 1 + std::distance (_M_grammar->rules.begin (), rule); 269 | } 270 | 271 | int Automaton::id (Name name) 272 | { 273 | return std::distance (_M_grammar->names.begin (), name); 274 | } 275 | 276 | int Automaton::id (StatePointer state) 277 | { 278 | return std::distance (states.begin (), state); 279 | } 280 | 281 | void Automaton::build () 282 | { 283 | Item item; 284 | item.rule = _M_grammar->goal; 285 | item.dot = _M_grammar->goal->rhs.begin (); 286 | 287 | State tmp (_M_grammar); 288 | tmp.insert (item); 289 | start = internState (tmp).first; 290 | 291 | closure (start); 292 | 293 | buildNullables (); 294 | buildLookbackSets (); 295 | buildReads (); 296 | buildIncludesAndFollows (); 297 | buildLookaheads (); 298 | buildDefaultReduceActions (); 299 | } 300 | 301 | void Automaton::buildNullables () 302 | { 303 | bool changed = true; 304 | 305 | while (changed) 306 | { 307 | changed = false; 308 | 309 | for (RulePointer rule = _M_grammar->rules.begin (); rule != _M_grammar->rules.end (); ++rule) 310 | { 311 | NameList::iterator nn = std::find_if (rule->rhs.begin (), rule->rhs.end (), std::not1 (_Nullable (this))); 312 | 313 | if (nn == rule->rhs.end ()) 314 | changed |= nullables.insert (rule->lhs).second; 315 | } 316 | } 317 | 318 | #ifndef QLALR_NO_DEBUG_NULLABLES 319 | qerr << "nullables = {" << nullables << endl; 320 | #endif 321 | } 322 | 323 | QPair Automaton::internState (const State &state) 324 | { 325 | StatePointer it = qFind (states.begin (), states.end (), state); 326 | 327 | if (it != states.end ()) 328 | return qMakePair (it, false); 329 | 330 | return qMakePair (states.insert (it, state), true); 331 | } 332 | 333 | struct _Bucket 334 | { 335 | QLinkedList items; 336 | 337 | void insert (ItemPointer item) 338 | { items.push_back (item); } 339 | 340 | State toState (Automaton *aut) 341 | { 342 | State st (aut->_M_grammar); 343 | 344 | for (QLinkedList::iterator item = items.begin (); item != items.end (); ++item) 345 | st.insert ((*item)->next ()); 346 | 347 | return st; 348 | } 349 | }; 350 | 351 | void Automaton::closure (StatePointer state) 352 | { 353 | if (! state->closure.empty ()) // ### not true. 354 | return; 355 | 356 | typedef QMap bucket_map_type; 357 | 358 | bucket_map_type buckets; 359 | QStack working_list; 360 | 361 | for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item) 362 | working_list.push (item); 363 | 364 | state->closure = state->kernel; 365 | 366 | while (! working_list.empty ()) 367 | { 368 | ItemPointer item = working_list.top (); 369 | working_list.pop (); 370 | 371 | if (item->isReduceItem ()) 372 | continue; 373 | 374 | buckets [*item->dot].insert (item); 375 | 376 | if (_M_grammar->isNonTerminal (*item->dot)) 377 | { 378 | foreach (RulePointer rule, _M_grammar->rule_map.values (*item->dot)) 379 | { 380 | Item ii; 381 | ii.rule = rule; 382 | ii.dot = rule->rhs.begin (); 383 | 384 | QPair r = state->insertClosure (ii); 385 | 386 | if (r.second) 387 | working_list.push (r.first); 388 | } 389 | } 390 | } 391 | 392 | QList todo; 393 | 394 | for (bucket_map_type::iterator bucket = buckets.begin (); bucket != buckets.end (); ++bucket) 395 | { 396 | QPair r = internState (bucket->toState (this)); 397 | 398 | StatePointer target = r.first; 399 | 400 | if (r.second) 401 | todo.push_back (target); 402 | 403 | state->bundle.insert (bucket.key(), target); 404 | } 405 | 406 | while (! todo.empty ()) 407 | { 408 | closure (todo.front ()); 409 | todo.pop_front (); 410 | } 411 | } 412 | 413 | void Automaton::buildLookbackSets () 414 | { 415 | for (StatePointer p = states.begin (); p != states.end (); ++p) 416 | { 417 | for (Bundle::iterator a = p->bundle.begin (); a != p->bundle.end (); ++a) 418 | { 419 | Name A = a.key (); 420 | 421 | if (! _M_grammar->isNonTerminal (A)) 422 | continue; 423 | 424 | foreach (RulePointer rule, _M_grammar->rule_map.values (A)) 425 | { 426 | StatePointer q = p; 427 | 428 | for (NameList::iterator dot = rule->rhs.begin (); dot != rule->rhs.end (); ++dot) 429 | q = q->bundle.value (*dot, states.end ()); 430 | 431 | Q_ASSERT (q != states.end ()); 432 | 433 | ItemPointer item = q->closure.begin (); 434 | 435 | for (; item != q->closure.end (); ++item) 436 | { 437 | if (item->rule == rule && item->dot == item->end_rhs ()) 438 | break; 439 | } 440 | 441 | if (item == q->closure.end ()) 442 | { 443 | Q_ASSERT (q == p); 444 | Q_ASSERT (rule->rhs.begin () == rule->rhs.end ()); 445 | 446 | for (item = q->closure.begin (); item != q->closure.end (); ++item) 447 | { 448 | if (item->rule == rule && item->dot == item->end_rhs ()) 449 | break; 450 | } 451 | } 452 | 453 | Q_ASSERT (item != q->closure.end ()); 454 | 455 | lookbacks.insert (item, Lookback (p, A)); 456 | 457 | #ifndef QLALR_NO_DEBUG_LOOKBACKS 458 | qerr << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl; 459 | #endif 460 | } 461 | } 462 | } 463 | } 464 | 465 | void Automaton::buildDirectReads () 466 | { 467 | for (StatePointer q = states.begin (); q != states.end (); ++q) 468 | { 469 | for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) 470 | { 471 | if (! _M_grammar->isNonTerminal (a.key ())) 472 | continue; 473 | 474 | StatePointer r = a.value (); 475 | 476 | for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z) 477 | { 478 | Name sym = z.key (); 479 | 480 | if (! _M_grammar->isTerminal (sym)) 481 | continue; 482 | 483 | q->reads [a.key ()].insert (sym); 484 | } 485 | } 486 | 487 | #ifndef QLALR_NO_DEBUG_DIRECT_READS 488 | for (QMap::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr) 489 | qerr << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl; 490 | #endif 491 | } 492 | } 493 | 494 | void Automaton::buildReadsDigraph () 495 | { 496 | for (StatePointer q = states.begin (); q != states.end (); ++q) 497 | { 498 | for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) 499 | { 500 | if (! _M_grammar->isNonTerminal (a.key ())) 501 | continue; 502 | 503 | StatePointer r = a.value (); 504 | 505 | for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z) 506 | { 507 | Name sym = z.key (); 508 | 509 | if (! _M_grammar->isNonTerminal(sym) || nullables.find (sym) == nullables.end ()) 510 | continue; 511 | 512 | ReadsGraph::iterator source = ReadsGraph::get (Read (q, a.key ())); 513 | ReadsGraph::iterator target = ReadsGraph::get (Read (r, sym)); 514 | 515 | source->insertEdge (target); 516 | 517 | #ifndef QLALR_NO_DEBUG_READS 518 | qerr << "*** "; 519 | dump (qerr, source); 520 | qerr << " reads "; 521 | dump (qerr, target); 522 | qerr << endl; 523 | #endif 524 | } 525 | } 526 | } 527 | } 528 | 529 | void Automaton::buildReads () 530 | { 531 | buildDirectReads (); 532 | buildReadsDigraph (); 533 | 534 | _M_reads_dfn = 0; 535 | 536 | for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node) 537 | { 538 | if (! node->root) 539 | continue; 540 | 541 | visitReadNode (node); 542 | } 543 | 544 | for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node) 545 | visitReadNode (node); 546 | } 547 | 548 | void Automaton::visitReadNode (ReadNode node) 549 | { 550 | if (node->dfn != 0) 551 | return; // nothing to do 552 | 553 | int N = node->dfn = ++_M_reads_dfn; 554 | _M_reads_stack.push (node); 555 | 556 | #ifndef QLALR_NO_DEBUG_INCLUDES 557 | // qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; 558 | #endif 559 | 560 | for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) 561 | { 562 | ReadsGraph::iterator r = *edge; 563 | 564 | visitReadNode (r); 565 | 566 | node->dfn = qMin (N, r->dfn); 567 | 568 | NameSet &dst = node->data.state->reads [node->data.nt]; 569 | NameSet &src = r->data.state->reads [r->data.nt]; 570 | dst.insert (src.begin (), src.end ()); 571 | } 572 | 573 | if (node->dfn == N) 574 | { 575 | ReadsGraph::iterator tos = _M_reads_stack.top (); 576 | 577 | do { 578 | tos = _M_reads_stack.top (); 579 | _M_reads_stack.pop (); 580 | tos->dfn = INT_MAX; 581 | } while (tos != node); 582 | } 583 | } 584 | 585 | void Automaton::buildIncludesAndFollows () 586 | { 587 | for (StatePointer p = states.begin (); p != states.end (); ++p) 588 | p->follows = p->reads; 589 | 590 | buildIncludesDigraph (); 591 | 592 | _M_includes_dfn = 0; 593 | 594 | for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node) 595 | { 596 | if (! node->root) 597 | continue; 598 | 599 | visitIncludeNode (node); 600 | } 601 | 602 | for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node) 603 | visitIncludeNode (node); 604 | } 605 | 606 | void Automaton::buildIncludesDigraph () 607 | { 608 | for (StatePointer pp = states.begin (); pp != states.end (); ++pp) 609 | { 610 | for (Bundle::iterator a = pp->bundle.begin (); a != pp->bundle.end (); ++a) 611 | { 612 | Name name = a.key (); 613 | 614 | if (! _M_grammar->isNonTerminal (name)) 615 | continue; 616 | 617 | foreach (RulePointer rule, _M_grammar->rule_map.values (name)) 618 | { 619 | StatePointer p = pp; 620 | 621 | for (NameList::iterator A = rule->rhs.begin (); A != rule->rhs.end (); ++A) 622 | { 623 | NameList::iterator dot = A; 624 | ++dot; 625 | 626 | if (_M_grammar->isNonTerminal (*A) && dot == rule->rhs.end ()) 627 | { 628 | // found an include edge. 629 | IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name)); 630 | IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A)); 631 | 632 | source->insertEdge (target); 633 | 634 | #ifndef QLALR_NO_DEBUG_INCLUDES 635 | qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; 636 | #endif // QLALR_NO_DEBUG_INCLUDES 637 | 638 | continue; 639 | } 640 | 641 | p = p->bundle.value (*A); 642 | 643 | if (! _M_grammar->isNonTerminal (*A)) 644 | continue; 645 | 646 | NameList::iterator first_not_nullable = std::find_if (dot, rule->rhs.end (), std::not1 (_Nullable (this))); 647 | if (first_not_nullable != rule->rhs.end ()) 648 | continue; 649 | 650 | // found an include edge. 651 | IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name)); 652 | IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A)); 653 | 654 | source->insertEdge (target); 655 | 656 | #ifndef QLALR_NO_DEBUG_INCLUDES 657 | qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; 658 | #endif // QLALR_NO_DEBUG_INCLUDES 659 | } 660 | } 661 | } 662 | } 663 | } 664 | 665 | void Automaton::visitIncludeNode (IncludeNode node) 666 | { 667 | if (node->dfn != 0) 668 | return; // nothing to do 669 | 670 | int N = node->dfn = ++_M_includes_dfn; 671 | _M_includes_stack.push (node); 672 | 673 | #ifndef QLALR_NO_DEBUG_INCLUDES 674 | // qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; 675 | #endif 676 | 677 | for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) 678 | { 679 | IncludesGraph::iterator r = *edge; 680 | 681 | visitIncludeNode (r); 682 | 683 | node->dfn = qMin (N, r->dfn); 684 | 685 | #ifndef QLALR_NO_DEBUG_INCLUDES 686 | qerr << "*** Merge. follows"; 687 | dump (qerr, node); 688 | qerr << " += follows"; 689 | dump (qerr, r); 690 | qerr << endl; 691 | #endif 692 | 693 | NameSet &dst = node->data.state->follows [node->data.nt]; 694 | NameSet &src = r->data.state->follows [r->data.nt]; 695 | 696 | dst.insert (src.begin (), src.end ()); 697 | } 698 | 699 | if (node->dfn == N) 700 | { 701 | IncludesGraph::iterator tos = _M_includes_stack.top (); 702 | 703 | do { 704 | tos = _M_includes_stack.top (); 705 | _M_includes_stack.pop (); 706 | tos->dfn = INT_MAX; 707 | } while (tos != node); 708 | } 709 | } 710 | 711 | void Automaton::buildLookaheads () 712 | { 713 | for (StatePointer p = states.begin (); p != states.end (); ++p) 714 | { 715 | for (ItemPointer item = p->closure.begin (); item != p->closure.end (); ++item) 716 | { 717 | foreach (Lookback lookback, lookbacks.values (item)) 718 | { 719 | StatePointer q = lookback.state; 720 | 721 | #ifndef QLALR_NO_DEBUG_LOOKAHEADS 722 | qerr << "(" << id (p) << ", " << *item->rule << ") lookbacks "; 723 | dump (qerr, lookback); 724 | qerr << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl; 725 | #endif 726 | 727 | lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ()); 728 | } 729 | } 730 | 731 | // propagate the lookahead in the kernel 732 | ItemPointer k = p->kernel.begin (); 733 | ItemPointer c = p->closure.begin (); 734 | 735 | for (; k != p->kernel.end (); ++k, ++c) 736 | lookaheads [k] = lookaheads [c]; 737 | } 738 | } 739 | 740 | void Automaton::buildDefaultReduceActions () 741 | { 742 | for (StatePointer state = states.begin (); state != states.end (); ++state) 743 | { 744 | ItemPointer def = state->closure.end (); 745 | int size = -1; 746 | 747 | for (ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item) 748 | { 749 | if (item->dot != item->end_rhs ()) 750 | continue; 751 | 752 | int la = lookaheads.value (item).size (); 753 | if (def == state->closure.end () || la > size) 754 | { 755 | def = item; 756 | size = la; 757 | } 758 | } 759 | 760 | if (def != state->closure.end ()) 761 | { 762 | Q_ASSERT (size >= 0); 763 | state->defaultReduce = def->rule; 764 | } 765 | } 766 | } 767 | 768 | void Automaton::dump (QTextStream &out, IncludeNode incl) 769 | { 770 | out << "(" << id (incl->data.state) << ", " << incl->data.nt << ")"; 771 | } 772 | 773 | void Automaton::dump (QTextStream &out, ReadNode rd) 774 | { 775 | out << "(" << id (rd->data.state) << ", " << rd->data.nt << ")"; 776 | } 777 | 778 | void Automaton::dump (QTextStream &out, const Lookback &lp) 779 | { 780 | out << "(" << id (lp.state) << ", " << lp.nt << ")"; 781 | } 782 | --------------------------------------------------------------------------------