├── .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" \
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 | "" \
40 | " " \
41 | " \n" \
42 | " " \
43 | "\n" \
57 | "
"
58 |
59 | HTML.footer = "
\n" \
60 | "
\n" \
61 | "Copyright © 2012 Digia Plc and/or its subsidiary(-ies) \n" \
62 | "Trademarks \n" \
63 | "Qt \\version
\n" \
64 | "
"
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 |
--------------------------------------------------------------------------------