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 /share | |
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 'share')
-rw-r--r-- | share/qbs/modules/lex_yacc/lexyacc.js | 79 | ||||
-rw-r--r-- | share/qbs/modules/lex_yacc/lexyacc.qbs | 68 |
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]; } |