aboutsummaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2018-04-30 14:50:03 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2018-05-04 05:19:20 +0000
commit2319531641817ef7d96a212b02aa0e763419fb00 (patch)
tree22e3d5243c96f28ac42e8fcc07d4e7d759fcc4fa /share
parent9258beb35aaf30ab2e89cdd6af0e02ddc179d98d (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 'share')
-rw-r--r--share/qbs/modules/lex_yacc/lexyacc.js79
-rw-r--r--share/qbs/modules/lex_yacc/lexyacc.qbs68
2 files changed, 121 insertions, 26 deletions
diff --git a/share/qbs/modules/lex_yacc/lexyacc.js b/share/qbs/modules/lex_yacc/lexyacc.js
index 05913f4e2..31474d323 100644
--- a/share/qbs/modules/lex_yacc/lexyacc.js
+++ b/share/qbs/modules/lex_yacc/lexyacc.js
@@ -1,15 +1,82 @@
var FileInfo = require("qbs.FileInfo");
+var TextFile = require("qbs.TextFile");
-function outputFilePath(product, input, posixFileName, forYacc)
+function unquote(s)
+{
+ return s.startsWith('"') && s.endsWith('"') ? s.substr(1, s.length - 2) : s;
+}
+
+function readLexOptions(filePath) {
+ var result = {};
+ var f = new TextFile(filePath, TextFile.ReadOnly);
+ var regex = /^%option\s+([^ \t=]+)(?:\s*=\s*(\S+))?/;
+ while (!f.atEof()) {
+ var line = f.readLine();
+ var m = regex.exec(line);
+ if (!m) {
+ if (line === "%%")
+ break;
+ continue;
+ }
+ result[m[1]] = m[2] || true;
+ }
+ f.close();
+ return result;
+}
+
+function lexOutputFilePath(input, posixFileName, options)
{
var outDir = input.lex_yacc.outputDir;
var fileName;
- if (input.lex_yacc.uniqueSymbolPrefix) {
+ if (options.outfile) {
+ fileName = unquote(options.outfile);
+ } else if (options.prefix) {
+ fileName = FileInfo.baseName(posixFileName) + '.'
+ + unquote(options.prefix) + '.'
+ + FileInfo.suffix(posixFileName);
+ } else if (input.lex_yacc.uniqueSymbolPrefix) {
fileName = input.baseName;
- if (forYacc)
- fileName += posixFileName.slice(1);
- else
- fileName += posixFileName;
+ fileName += posixFileName;
+ } else {
+ fileName = posixFileName;
+ }
+ return FileInfo.joinPaths(outDir, fileName);
+}
+
+function readYaccOptions(filePath) {
+ var result = {};
+ var f = new TextFile(filePath, TextFile.ReadOnly);
+ var regex = /^%output\s+(.+)/;
+ while (!f.atEof()) {
+ var line = f.readLine();
+ var m = regex.exec(line);
+ if (!m) {
+ if (line === "%%")
+ break;
+ continue;
+ }
+ result.output = m[1];
+ break;
+ }
+ f.close();
+ return result;
+}
+
+function yaccOutputFilePath(input, posixFileName, options)
+{
+ var outDir = input.lex_yacc.outputDir;
+ var fileName;
+ if (options.output) {
+ var outputFileName = unquote(options.output);
+ var suffix = FileInfo.suffix(posixFileName);
+ if (suffix === "c") {
+ fileName = outputFileName;
+ } else {
+ fileName = FileInfo.completeBaseName(outputFileName)
+ + '.' + suffix + FileInfo.suffix(outputFileName).slice(1);
+ }
+ } else if (input.lex_yacc.uniqueSymbolPrefix) {
+ fileName = input.baseName + posixFileName.slice(1);
} else {
fileName = posixFileName;
}
diff --git a/share/qbs/modules/lex_yacc/lexyacc.qbs b/share/qbs/modules/lex_yacc/lexyacc.qbs
index b60f7ca8f..20982f7aa 100644
--- a/share/qbs/modules/lex_yacc/lexyacc.qbs
+++ b/share/qbs/modules/lex_yacc/lexyacc.qbs
@@ -9,6 +9,8 @@ Module {
property string yaccBinary: "yacc"
property string outputTag: "c"
property bool uniqueSymbolPrefix: false
+ property string lexOutputFilePath
+ property string yaccOutputFilePath
property stringList lexFlags: []
property stringList yaccFlags: []
@@ -16,17 +18,29 @@ Module {
Rule {
inputs: ["lex.input"]
- Artifact {
- filePath: HelperFunctions.outputFilePath(product, input, "lex.yy.c", false)
- fileTags: [product.lex_yacc.outputTag]
- cpp.includePaths: (input.cpp.includePaths || [])
- .concat([input.lex_yacc.outputDir])
- cpp.warningLevel: input.moduleProperty("lex_yacc", "enableCompilerWarnings")
- ? "all" : "none"
+ outputFileTags: [product.lex_yacc.outputTag]
+ outputArtifacts: {
+ var output = {
+ fileTags: [product.lex_yacc.outputTag],
+ lex_yacc: {},
+ };
+ var options = HelperFunctions.readLexOptions(input.filePath);
+ if (!options.outfile && input.lex_yacc.lexOutputFilePath) {
+ options.outfile = input.lex_yacc.lexOutputFilePath;
+ output.lex_yacc.useOutfileFromModule = true;
+ }
+ output.filePath = HelperFunctions.lexOutputFilePath(input, "lex.yy.c", options);
+ output.cpp = {
+ includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir),
+ warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none",
+ };
+ return [output];
}
prepare: {
var args = input.lex_yacc.lexFlags;
- if (input.lex_yacc.uniqueSymbolPrefix)
+ if (output.lex_yacc.useOutfileFromModule)
+ args.push("-o" + input.lex_yacc.lexOutputFilePath);
+ else if (input.lex_yacc.uniqueSymbolPrefix)
args.push("-P" + input.baseName, "-o" + output.filePath);
args.push(input.filePath);
var cmd = new Command(input.lex_yacc.lexBinary, args);
@@ -38,27 +52,41 @@ Module {
Rule {
inputs: ["yacc.input"]
- Artifact {
- filePath: HelperFunctions.outputFilePath(product, input, "y.tab.c", true)
- fileTags: [product.lex_yacc.outputTag]
- cpp.warningLevel: input.moduleProperty("lex_yacc", "enableCompilerWarnings")
- ? "all" : "none"
- }
- Artifact {
- filePath: HelperFunctions.outputFilePath(product, input, "y.tab.h", true)
- fileTags: ["hpp"]
+ outputFileTags: [product.lex_yacc.outputTag, "hpp"]
+ outputArtifacts: {
+ var src = {
+ fileTags: [product.lex_yacc.outputTag],
+ lex_yacc: {},
+ };
+ var options = HelperFunctions.readYaccOptions(input.filePath);
+ if (!options.output && input.lex_yacc.yaccOutputFilePath) {
+ options.output = input.lex_yacc.yaccOutputFilePath;
+ src.lex_yacc.useOutputFromModule = true;
+ }
+ var hdr = {
+ filePath: HelperFunctions.yaccOutputFilePath(input, "y.tab.h", options),
+ fileTags: ["hpp"],
+ };
+ src.filePath = HelperFunctions.yaccOutputFilePath(input, "y.tab.c", options);
+ src.cpp = {
+ includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir),
+ warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none",
+ };
+ return [hdr, src];
}
prepare: {
var args = input.lex_yacc.yaccFlags;
args.push("-d");
- if (input.lex_yacc.uniqueSymbolPrefix) {
+ var impl = outputs[input.lex_yacc.outputTag][0];
+ if (impl.lex_yacc.useOutputFromModule)
+ args.push("-o" + input.lex_yacc.yaccOutputFilePath);
+ else if (input.lex_yacc.uniqueSymbolPrefix)
args.push("-b", input.baseName, "-p", input.baseName);
- }
args.push(input.filePath);
var cmd = new Command(input.lex_yacc.yaccBinary, args);
cmd.workingDirectory = input.lex_yacc.outputDir;
cmd.description = "generating "
- + outputs[input.lex_yacc.outputTag][0].fileName
+ + impl.fileName
+ " and " + outputs["hpp"][0].fileName;
return [cmd];
}