diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2018-04-30 14:50:03 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2018-05-04 05:19:20 +0000 |
commit | 2319531641817ef7d96a212b02aa0e763419fb00 (patch) | |
tree | 22e3d5243c96f28ac42e8fcc07d4e7d759fcc4fa /tests | |
parent | 9258beb35aaf30ab2e89cdd6af0e02ddc179d98d (diff) |
Add support for prefix/output in lex_yacc module
The user can specify the outputs of lex/yacc via
%option prefix="foo"
in the .l file and
%output "parser.cpp"
in the .y file.
Also, introduce the following properties to specify the outputs:
lexOutputFilePath, yaccOutputFilePath.
Scan the lex/yacc inputs for those specifications and adjust the output
artifacts accordingly.
[ChangeLog] Added support for %option outfile and %output to the
lex_yacc module.
Change-Id: I5437c737ae8da54dc7eda81ac7384727f00f9d1f
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'tests')
14 files changed, 415 insertions, 3 deletions
diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lex_outfile.qbs b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lex_outfile.qbs new file mode 100644 index 000000000..677828906 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lex_outfile.qbs @@ -0,0 +1,16 @@ +import qbs + +CppApplication { + Depends { name: "lex_yacc" } + lex_yacc.outputTag: "cpp" + lex_yacc.yaccFlags: ["-l"] + cpp.includePaths: ["."] + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.7" + consoleApplication: true + files: [ + "lexer.l", + "parser.y", + "types.h", + ] +} diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lexer.l b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lexer.l new file mode 100644 index 000000000..07115405d --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lexer.l @@ -0,0 +1,21 @@ +%option outfile="quark.cpp" +%{ +#include <types.h> +void yyerror(const char *e) { std::cerr << e; } +extern "C" int yywrap() { return 1; } +extern YYSTYPE yylval; +%} + +ID [a-z]+ +AND "&&" +OR "||" +NOT "!" + +%% +[[:space:]]+ +{ID} yylval.s = yytext; return 1; +{AND} return 2; +{OR} return 3; +{NOT} return 4; + +%% diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_outfile/parser.y b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/parser.y new file mode 100644 index 000000000..e19c9a90b --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/parser.y @@ -0,0 +1,30 @@ +%{ +#include <types.h> +%} + +%type <t> expr +%left OR +%left AND +%nonassoc NOT +%token <s> ID + +%% + +start: expr { root = $1; } +expr: expr AND expr { auto t = std::make_shared<Tree>(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } + | expr OR expr { auto t = std::make_shared<Tree>(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } + | NOT expr { auto t = std::make_shared<Tree>(); t->val = "NOT"; t->children = { $2 }; $$ = t; } + | ID { auto t = std::make_shared<Tree>(); t->val = $1; $$ = t; } + +%% + +TreePtr root; + +int main() +{ + yyparse(); + if (!root) + return 1; + root->print(); + std::cout << std::endl; +} diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_outfile/types.h b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/types.h new file mode 100644 index 000000000..12cafe890 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_outfile/types.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <iostream> +#include <memory> +#include <string> +#include <vector> + +struct Tree; +using TreePtr = std::shared_ptr<Tree>; +struct Tree { + std::string val; + std::vector<TreePtr> children; + void print() const { + std::cout << val << ' '; + for (const TreePtr &t : children) + t->print(); + } +}; +struct YaccType { TreePtr t; std::string s; }; +#define YYSTYPE YaccType +extern TreePtr root; + +int yylex(); +void yyerror(const char *); diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lex_prefix.qbs b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lex_prefix.qbs new file mode 100644 index 000000000..677828906 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lex_prefix.qbs @@ -0,0 +1,16 @@ +import qbs + +CppApplication { + Depends { name: "lex_yacc" } + lex_yacc.outputTag: "cpp" + lex_yacc.yaccFlags: ["-l"] + cpp.includePaths: ["."] + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.7" + consoleApplication: true + files: [ + "lexer.l", + "parser.y", + "types.h", + ] +} diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lexer.l b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lexer.l new file mode 100644 index 000000000..cbbc79fbc --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lexer.l @@ -0,0 +1,21 @@ +%option prefix="bla" +%{ +#include <types.h> +void blaerror(const char *e) { std::cerr << e; } +extern "C" int blawrap() { return 1; } +extern BLASTYPE blalval; +%} + +ID [a-z]+ +AND "&&" +OR "||" +NOT "!" + +%% +[[:space:]]+ +{ID} blalval.s = blatext; return 1; +{AND} return 2; +{OR} return 3; +{NOT} return 4; + +%% diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_prefix/parser.y b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/parser.y new file mode 100644 index 000000000..17ec6700b --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/parser.y @@ -0,0 +1,31 @@ +%{ +#include <types.h> +%} + +%define api.prefix {bla} +%type <t> expr +%left OR +%left AND +%nonassoc NOT +%token <s> ID + +%% + +start: expr { root = $1; } +expr: expr AND expr { auto t = std::make_shared<Tree>(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } + | expr OR expr { auto t = std::make_shared<Tree>(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } + | NOT expr { auto t = std::make_shared<Tree>(); t->val = "NOT"; t->children = { $2 }; $$ = t; } + | ID { auto t = std::make_shared<Tree>(); t->val = $1; $$ = t; } + +%% + +TreePtr root; + +int main() +{ + blaparse(); + if (!root) + return 1; + root->print(); + std::cout << std::endl; +} diff --git a/tests/auto/blackbox/testdata/lexyacc/lex_prefix/types.h b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/types.h new file mode 100644 index 000000000..e0682141c --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/lex_prefix/types.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <iostream> +#include <memory> +#include <string> +#include <vector> + +struct Tree; +using TreePtr = std::shared_ptr<Tree>; +struct Tree { + std::string val; + std::vector<TreePtr> children; + void print() const { + std::cout << val << ' '; + for (const TreePtr &t : children) + t->print(); + } +}; +struct YaccType { TreePtr t; std::string s; }; +#define BLASTYPE YaccType +extern TreePtr root; + +int blalex(); +void blaerror(const char *); diff --git a/tests/auto/blackbox/testdata/lexyacc/yacc_output/lexer.l b/tests/auto/blackbox/testdata/lexyacc/yacc_output/lexer.l new file mode 100644 index 000000000..600ff2832 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/yacc_output/lexer.l @@ -0,0 +1,21 @@ +%{ +#include <types.h> +#include <parser.hxx> +void yyerror(const char *e) { std::cerr << e; } +extern "C" int yywrap() { return 1; } +extern YYSTYPE yylval; +%} + +ID [a-z]+ +AND "&&" +OR "||" +NOT "!" + +%% +[[:space:]]+ +{ID} yylval.s = yytext; return ID; +{AND} return AND; +{OR} return OR; +{NOT} return NOT; + +%% diff --git a/tests/auto/blackbox/testdata/lexyacc/yacc_output/parser.y b/tests/auto/blackbox/testdata/lexyacc/yacc_output/parser.y new file mode 100644 index 000000000..111e20bc5 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/yacc_output/parser.y @@ -0,0 +1,31 @@ +%{ +#include <types.h> +%} + +%output "parser.cxx" +%type <t> expr +%left OR +%left AND +%nonassoc NOT +%token <s> ID + +%% + +start: expr { root = $1; } +expr: expr AND expr { auto t = std::make_shared<Tree>(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } + | expr OR expr { auto t = std::make_shared<Tree>(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } + | NOT expr { auto t = std::make_shared<Tree>(); t->val = "NOT"; t->children = { $2 }; $$ = t; } + | ID { auto t = std::make_shared<Tree>(); t->val = $1; $$ = t; } + +%% + +TreePtr root; + +int main() +{ + yyparse(); + if (!root) + return 1; + root->print(); + std::cout << std::endl; +} diff --git a/tests/auto/blackbox/testdata/lexyacc/yacc_output/types.h b/tests/auto/blackbox/testdata/lexyacc/yacc_output/types.h new file mode 100644 index 000000000..12cafe890 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/yacc_output/types.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <iostream> +#include <memory> +#include <string> +#include <vector> + +struct Tree; +using TreePtr = std::shared_ptr<Tree>; +struct Tree { + std::string val; + std::vector<TreePtr> children; + void print() const { + std::cout << val << ' '; + for (const TreePtr &t : children) + t->print(); + } +}; +struct YaccType { TreePtr t; std::string s; }; +#define YYSTYPE YaccType +extern TreePtr root; + +int yylex(); +void yyerror(const char *); diff --git a/tests/auto/blackbox/testdata/lexyacc/yacc_output/yacc_output.qbs b/tests/auto/blackbox/testdata/lexyacc/yacc_output/yacc_output.qbs new file mode 100644 index 000000000..677828906 --- /dev/null +++ b/tests/auto/blackbox/testdata/lexyacc/yacc_output/yacc_output.qbs @@ -0,0 +1,16 @@ +import qbs + +CppApplication { + Depends { name: "lex_yacc" } + lex_yacc.outputTag: "cpp" + lex_yacc.yaccFlags: ["-l"] + cpp.includePaths: ["."] + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.7" + consoleApplication: true + files: [ + "lexer.l", + "parser.y", + "types.h", + ] +} diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 75721370c..e548a0236 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -144,6 +144,12 @@ QString TestBlackbox::findArchiver(const QString &fileName, int *status) return binary; } +bool TestBlackbox::lexYaccExist() +{ + return !findExecutable(QStringList("lex")).isEmpty() + && !findExecutable(QStringList("yacc")).isEmpty(); +} + void TestBlackbox::sevenZip() { QDir::setCurrent(testDataDir + "/archiver"); @@ -3910,10 +3916,8 @@ void TestBlackbox::linkerMode() void TestBlackbox::lexyacc() { - if (findExecutable(QStringList("lex")).isEmpty() - || findExecutable(QStringList("yacc")).isEmpty()) { + if (!lexYaccExist()) QSKIP("lex or yacc not present"); - } QDir::setCurrent(testDataDir + "/lexyacc/one-grammar"); QCOMPARE(runQbs(), 0); const QString parserBinary = relativeExecutableFilePath("one-grammar"); @@ -3944,6 +3948,58 @@ void TestBlackbox::lexyacc() QVERIFY2(m_qbsStderr.contains("whatever"), m_qbsStderr.constData()); } +void TestBlackbox::lexyaccOutputs() +{ + if (!lexYaccExist()) + QSKIP("lex or yacc not present"); + + QFETCH(QString, lexOutputFilePath); + QFETCH(QString, yaccOutputFilePath); + QbsRunParameters params; + if (!lexOutputFilePath.isEmpty()) + params.arguments << "modules.lex_yacc.lexOutputFilePath:" + lexOutputFilePath; + if (!yaccOutputFilePath.isEmpty()) + params.arguments << "modules.lex_yacc.yaccOutputFilePath:" + yaccOutputFilePath; + +#define VERIFY_COMPILATION(file) \ + if (!file.isEmpty()) { \ + QByteArray expected = "compiling " + file.toUtf8(); \ + if (!m_qbsStdout.contains(expected)) { \ + qDebug() << "Expected output:" << expected; \ + qDebug() << "Actual output:" << m_qbsStdout; \ + QFAIL("Expected stdout content missing."); \ + } \ + } + + QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_prefix")); + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(params), 0); + VERIFY_COMPILATION(yaccOutputFilePath); + + QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_outfile")); + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(params), 0); + VERIFY_COMPILATION(yaccOutputFilePath); + + QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/yacc_output")); + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(params), 0); + VERIFY_COMPILATION(lexOutputFilePath); + +#undef VERIFY_COMPILATION +} + +void TestBlackbox::lexyaccOutputs_data() +{ + QTest::addColumn<QString>("lexOutputFilePath"); + QTest::addColumn<QString>("yaccOutputFilePath"); + QTest::newRow("none") << QString() << QString(); + QTest::newRow("lexOutputFilePath") + << QString{"lex_luthor.cpp"} << QString(); + QTest::newRow("yaccOutputFilePath") + << QString() << QString{"shaven_yak.cpp"}; +} + void TestBlackbox::linkerScripts() { const SettingsPtr s = settings(); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index ac515d0c0..746c885fa 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -145,6 +145,8 @@ private slots: void ld(); void linkerMode(); void lexyacc(); + void lexyaccOutputs(); + void lexyaccOutputs_data(); void linkerScripts(); void listProducts(); void listPropertiesWithOuter(); @@ -267,6 +269,7 @@ private: QMap<QString, QString> findNodejs(int *status); QMap<QString, QString> findTypeScript(int *status); QString findArchiver(const QString &fileName, int *status = nullptr); + static bool lexYaccExist(); }; #endif // TST_BLACKBOX_H |