1
0
Fork 0
mirror of https://github.com/Reuh/candran.git synced 2025-10-27 09:59:29 +00:00

Use argparse to parse CLI args, separate preprocessor constants from options

This commit is contained in:
Étienne Fildadut 2021-06-17 19:45:53 +02:00
parent dd22f2de3d
commit e9ae8e21a3
8 changed files with 253 additions and 346 deletions

View file

@ -493,7 +493,7 @@ _assert(5 = 2, "failed") -- replaced with if 5 = 2 then error("failed") end
Candran provide some predefined macros by default:
* `__STR__(expr)`: returns a string litteral representing the expression (e.g., `__STR__(5 + 2)` expands to `"5 + 2"`)
* `__CONSTEXPR__(expr)`: calculate the result of the expression in the preprocessor, and returns a representation of the returned value, i.e. precalculate an expression at compile time
You can disable these built-in macros using the `noBuiltInMacros` compiler option.
You can disable these built-in macros using the `builtInMacros` compiler option.
Compile targets
---------------
@ -663,14 +663,15 @@ at the top of your main Lua file. If a Candran file is found when you call ```re
You can give arbitrary options to the compiler and preprocessor, but Candran already provide and uses these with their associated default values:
```lua
target = "lua53" -- compiler target. "lua53", "lua52", "luajit" or "lua51" (default is automatically selected based on the Lua version used).
target = "lua53" -- compiler target. "lua54", "lua53", "lua52", "luajit" or "lua51" (default is automatically selected based on the Lua version used).
indentation = "" -- character(s) used for indentation in the compiled file.
newline = "\n" -- character(s) used for newlines in the compiled file.
variablePrefix = "__CAN_" -- Prefix used when Candran needs to set a local variable to provide some functionality (example: to load LuaJIT's bit lib when using bitwise operators).
mapLines = true -- if true, compiled files will contain comments at the end of each line indicating the associated line and source file. Needed for error rewriting.
chunkname = "nil" -- the chunkname used when running code using the helper functions and writing the line origin comments. Candran will try to set it to the original filename if it knows it.
rewriteErrors = true -- true to enable error rewriting when loading code using the helper functions. Will wrap the whole code in a xpcall().
noBuiltInMacros = false -- true to disable built-in macros __*__
builtInMacros = true -- false to disable built-in macros __*__
preprocessorEnv = {} -- environment to merge with the preprocessor environement
```
You can change the defaults used for these variables in the table `candran.default`.

44
bin/can
View file

@ -1,28 +1,30 @@
#!/usr/bin/env lua
local candran = require("candran").setup()
local cmdline = require("candran.cmdline")
local util = require("candran.util")
local argparse = require("argparse")
local args = cmdline(arg)
-- Parse args --
if args.help or args.h then
print("Candran "..candran.VERSION.." interpreter by Reuh")
print("Usage: "..arg[0].." [options] filename")
print("Specify no options to start the REPL.")
print("Use - instead of a filename to read from the standard input.")
print("Interpreter options:")
print(" -help or -h print this text")
print("Default options:")
for opt, val in pairs(candran.default) do
if type(val) == "string" then val = val:gsub("\n", "\\n") end
print((" %s=%q"):format(opt, tostring(val)))
end
return
end
local parser = argparse()
:name "can"
:description("Candran "..candran.VERSION.." interpreter by Reuh.")
:epilog "For more info, see https://github.com/Reuh/candran"
parser:argument("filename", "Candran file to run. Use - to read from standard input. Start the REPL if no filename given.")
:args "?"
util.cli.addCandranOptions(parser)
local args = parser:parse()
local options = util.cli.makeCandranOptions(args)
-- Run --
-- stdin
if arg[#arg] == "-" then
local f, err = candran.load(io.read("*a"), "stdin", nil, args)
if args.filename == "-" then
local f, err = candran.load(io.read("*a"), "stdin", nil, options)
if not f then
io.stderr:write("can: "..err.."\n")
os.exit(1)
@ -33,8 +35,8 @@ if arg[#arg] == "-" then
os.exit(1)
end
-- file
elseif #args >= 1 then
local f, err = candran.loadfile(args[1], nil, args)
elseif args.filename then
local f, err = candran.loadfile(args.filename, nil, options)
if not f then
io.stderr:write("can: "..err.."\n")
os.exit(1)
@ -47,6 +49,8 @@ elseif #args >= 1 then
end
-- REPL
else
candran.default = util.merge(candran.default, options)
-- Setup linenoise
local s, l = pcall(require, "linenoise")
if not s then -- pure Lua compatibility thingy

View file

@ -1,48 +1,63 @@
#!/usr/bin/env lua
local candran = require("candran")
local cmdline = require("candran.cmdline")
local parse = require("candran.can-parser.parser").parse
local pp = require("candran.can-parser.pp")
local util = require("candran.util")
local argparse = require("argparse")
local args = cmdline(arg)
-- Parse args --
if #arg < 1 or args.help or args.h then
print("Candran "..candran.VERSION.." compiler by Reuh")
print("Usage: "..arg[0].." [options] filenames...")
print("Use - instead of filenames to read from the standard input. The output file will be named stdin.lua by default.")
print("Compiler options:")
print(" dest=\"directory\" where compiled files should be written")
print(" out=\"name.lua\" output filename. By default, will use the same name as the input file with a .lua extension.")
print(" -print write to the standard output instead of creating files")
print(" -preprocess only run the preprocessor")
print(" -compile only run the compiler")
print(" -parse only parse the file and prints errors to stdout")
print(" -ast (for debugging purposes) only parse the files and dump the AST to stdout")
print(" -help or -h print this text")
print("Default options:")
for opt, val in pairs(candran.default) do
if type(val) == "string" then val = val:gsub("\n", "\\n") end
print((" %s=%q"):format(opt, tostring(val)))
end
return
end
local parser = argparse()
:name "canc"
:description("Candran "..candran.VERSION.." compiler by Reuh.")
:epilog "For more info, see https://github.com/Reuh/candran"
if arg[#arg] == "-" then
table.insert(args, io.stdin)
end
parser:argument("filename", "Candran files to compile. Use - to read from standard input; the output file will then be named stdin.lua by default.")
:args "+"
for _, file in ipairs(args) do
parser:group("Output options",
parser:option("-d --destination")
:description "Where compiled files should be written"
:argname "directory",
parser:option("-o --output")
:description "Output filename. (default: same name as the input file with a .lua extension)"
:argname "filename",
parser:flag("-p --print")
:description "Write to the standard output instead of creating files",
parser:flag("--preprocess")
:description "Only run the preprocessor",
parser:flag("--compile")
:description "Only run the compiler",
parser:flag("--parse")
:description "Only parse the file and prints syntax errors to stdout",
parser:flag("--ast")
:description"(for debugging purposes) Only parse the files and dump the AST to stdout"
)
util.cli.addCandranOptions(parser)
local args = parser:parse()
-- Compile --
for _, file in ipairs(args.filename) do
-- Read
local dest, input
if file == io.stdin then
dest = args.out or "stdin.lua"
if file == "-" then
dest = args.output or "stdin.lua"
input = io.read("*a")
args.chunkname = "stdin"
else
dest = args.out or (file:gsub("%.can$", "")..".lua")
dest = args.output or (file:gsub("%.can$", "")..".lua")
local inputFile, err = io.open(file, "r")
if not inputFile then
@ -69,8 +84,10 @@ for _, file in ipairs(args) do
end
-- Compile and output
if args.dest then
dest = args.dest .. "/" .. dest
local options = util.cli.makeCandranOptions(args)
if args.destination then
dest = args.destination .. "/" .. dest
end
if not args.print then
@ -79,7 +96,7 @@ for _, file in ipairs(args) do
local out = input
if args.preprocess then
local r, err = candran.preprocess(out, args)
local r, err = candran.preprocess(out, options)
if not r then
io.stderr:write("canc: "..err.."\n")
os.exit(1)
@ -87,7 +104,7 @@ for _, file in ipairs(args) do
out = r
end
if args.compile then
local r, err = candran.compile(out, args)
local r, err = candran.compile(out, options)
if not r then
io.stderr:write("canc: "..err.."\n")
os.exit(1)
@ -95,7 +112,7 @@ for _, file in ipairs(args) do
out = r
end
if args.compile == nil and args.preprocess == nil then
local r, err = candran.make(input, args)
local r, err = candran.make(input, options)
if not r then
io.stderr:write("canc: "..err.."\n")
os.exit(1)

View file

@ -1,5 +1,4 @@
#import("candran.util")
#import("candran.cmdline")
#import("candran.serpent")
#import("compiler.lua54")
@ -29,7 +28,8 @@ candran.default = {
mapLines = true,
chunkname = "nil",
rewriteErrors = true,
noBuiltInMacros = false
builtInMacros = true,
preprocessorEnv = {}
}
-- Autodetect version
@ -92,7 +92,7 @@ function candran.preprocess(input, options={})
preprocessor ..= "return output"
-- make preprocessor environement
local env = util.merge(_G, options)
local env = util.merge(_G, options.preprocessorEnv)
--- Candran library table
env.candran = candran
--- Current preprocessor output
@ -179,7 +179,7 @@ function candran.preprocess(input, options={})
end
-- default macros
if not options.noBuiltInMacros then
if options.builtInMacros then
env.define("__STR__(x)", function(x) return ("%q"):format(x) end)
local s = require("candran.serpent")
env.define("__CONSTEXPR__(expr)", function(expr)

View file

@ -1,147 +1,90 @@
local function _() -- candran.can:2
local util = {} -- ./candran/util.can:1
util["search"] = function(modpath, exts) -- ./candran/util.can:3
if exts == nil then exts = {} end -- ./candran/util.can:3
for _, ext in ipairs(exts) do -- ./candran/util.can:4
for path in package["path"]:gmatch("[^;]+") do -- ./candran/util.can:5
local fpath = path:gsub("%.lua", "." .. ext):gsub("%?", (modpath:gsub("%.", "/"))) -- ./candran/util.can:6
local f = io["open"](fpath) -- ./candran/util.can:7
if f then -- ./candran/util.can:8
f:close() -- ./candran/util.can:9
return fpath -- ./candran/util.can:10
end -- ./candran/util.can:10
end -- ./candran/util.can:10
end -- ./candran/util.can:10
end -- ./candran/util.can:10
util["load"] = function(str, name, env) -- ./candran/util.can:16
if _VERSION == "Lua 5.1" then -- ./candran/util.can:17
local fn, err = loadstring(str, name) -- ./candran/util.can:18
if not fn then -- ./candran/util.can:19
return fn, err -- ./candran/util.can:19
end -- ./candran/util.can:19
return env ~= nil and setfenv(fn, env) or fn -- ./candran/util.can:20
else -- ./candran/util.can:20
if env then -- ./candran/util.can:22
return load(str, name, nil, env) -- ./candran/util.can:23
else -- ./candran/util.can:23
return load(str, name) -- ./candran/util.can:25
end -- ./candran/util.can:25
end -- ./candran/util.can:25
end -- ./candran/util.can:25
util["recmerge"] = function(...) -- ./candran/util.can:30
local r = {} -- ./candran/util.can:31
for _, t in ipairs({ ... }) do -- ./candran/util.can:32
for k, v in pairs(t) do -- ./candran/util.can:33
if type(v) == "table" then -- ./candran/util.can:34
r[k] = util["merge"](v, r[k]) -- ./candran/util.can:35
else -- ./candran/util.can:35
r[k] = v -- ./candran/util.can:37
end -- ./candran/util.can:37
end -- ./candran/util.can:37
end -- ./candran/util.can:37
return r -- ./candran/util.can:41
end -- ./candran/util.can:41
util["merge"] = function(...) -- ./candran/util.can:44
local r = {} -- ./candran/util.can:45
for _, t in ipairs({ ... }) do -- ./candran/util.can:46
for k, v in pairs(t) do -- ./candran/util.can:47
r[k] = v -- ./candran/util.can:48
end -- ./candran/util.can:48
end -- ./candran/util.can:48
return r -- ./candran/util.can:51
end -- ./candran/util.can:51
return util -- ./candran/util.can:54
end -- ./candran/util.can:54
local util = _() or util -- ./candran/util.can:58
package["loaded"]["candran.util"] = util or true -- ./candran/util.can:59
local function _() -- ./candran/util.can:62
local ipairs, pairs, setfenv, tonumber, loadstring, type = ipairs, pairs, setfenv, tonumber, loadstring, type -- ./candran/cmdline.lua:5
local tinsert, tconcat = table["insert"], table["concat"] -- ./candran/cmdline.lua:6
local function commonerror(msg) -- ./candran/cmdline.lua:8
return nil, ("[cmdline]: " .. msg) -- ./candran/cmdline.lua:9
end -- ./candran/cmdline.lua:9
local function argerror(msg, numarg) -- ./candran/cmdline.lua:12
msg = msg and (": " .. msg) or "" -- ./candran/cmdline.lua:13
return nil, ("[cmdline]: bad argument #" .. numarg .. msg) -- ./candran/cmdline.lua:14
end -- ./candran/cmdline.lua:14
local function iderror(numarg) -- ./candran/cmdline.lua:17
return argerror("ID not valid", numarg) -- ./candran/cmdline.lua:18
end -- ./candran/cmdline.lua:18
local function idcheck(id) -- ./candran/cmdline.lua:21
return id:match("^[%a_][%w_]*$") and true -- ./candran/cmdline.lua:22
end -- ./candran/cmdline.lua:22
return function(t_in, options, params) -- ./candran/cmdline.lua:73
local t_out = {} -- ./candran/cmdline.lua:74
for i, v in ipairs(t_in) do -- ./candran/cmdline.lua:75
local prefix, command = v:sub(1, 1), v:sub(2) -- ./candran/cmdline.lua:76
if prefix == "$" then -- ./candran/cmdline.lua:77
tinsert(t_out, command) -- ./candran/cmdline.lua:78
elseif prefix == "-" then -- ./candran/cmdline.lua:79
for id in command:gmatch("[^,;]+") do -- ./candran/cmdline.lua:80
if not idcheck(id) then -- ./candran/cmdline.lua:81
return iderror(i) -- ./candran/cmdline.lua:81
end -- ./candran/cmdline.lua:81
t_out[id] = true -- ./candran/cmdline.lua:82
end -- ./candran/cmdline.lua:82
elseif prefix == "!" then -- ./candran/cmdline.lua:84
local f, err = loadstring(command) -- ./candran/cmdline.lua:85
if not f then -- ./candran/cmdline.lua:86
return argerror(err, i) -- ./candran/cmdline.lua:86
end -- ./candran/cmdline.lua:86
setfenv(f, t_out)() -- ./candran/cmdline.lua:87
elseif v:find("=") then -- ./candran/cmdline.lua:88
local ids, val = v:match("^([^=]+)%=(.*)") -- ./candran/cmdline.lua:89
if not ids then -- ./candran/cmdline.lua:90
return argerror("invalid assignment syntax", i) -- ./candran/cmdline.lua:90
end -- ./candran/cmdline.lua:90
if val == "false" then -- ./candran/cmdline.lua:91
val = false -- ./candran/cmdline.lua:92
elseif val == "true" then -- ./candran/cmdline.lua:93
val = true -- ./candran/cmdline.lua:94
else -- ./candran/cmdline.lua:94
val = val:sub(1, 1) == "$" and val:sub(2) or tonumber(val) or val -- ./candran/cmdline.lua:96
end -- ./candran/cmdline.lua:96
for id in ids:gmatch("[^,;]+") do -- ./candran/cmdline.lua:98
if not idcheck(id) then -- ./candran/cmdline.lua:99
return iderror(i) -- ./candran/cmdline.lua:99
end -- ./candran/cmdline.lua:99
t_out[id] = val -- ./candran/cmdline.lua:100
end -- ./candran/cmdline.lua:100
else -- ./candran/cmdline.lua:100
tinsert(t_out, v) -- ./candran/cmdline.lua:103
end -- ./candran/cmdline.lua:103
end -- ./candran/cmdline.lua:103
if options then -- ./candran/cmdline.lua:106
local lookup, unknown = {}, {} -- ./candran/cmdline.lua:107
for _, v in ipairs(options) do -- ./candran/cmdline.lua:108
lookup[v] = true -- ./candran/cmdline.lua:108
end -- ./candran/cmdline.lua:108
for k, _ in pairs(t_out) do -- ./candran/cmdline.lua:109
if lookup[k] == nil and type(k) == "string" then -- ./candran/cmdline.lua:110
tinsert(unknown, k) -- ./candran/cmdline.lua:110
end -- ./candran/cmdline.lua:110
end -- ./candran/cmdline.lua:110
if # unknown > 0 then -- ./candran/cmdline.lua:112
return commonerror("unknown options: " .. tconcat(unknown, ", ")) -- ./candran/cmdline.lua:113
end -- ./candran/cmdline.lua:113
end -- ./candran/cmdline.lua:113
if params then -- ./candran/cmdline.lua:116
local missing = {} -- ./candran/cmdline.lua:117
for _, v in ipairs(params) do -- ./candran/cmdline.lua:118
if t_out[v] == nil then -- ./candran/cmdline.lua:119
tinsert(missing, v) -- ./candran/cmdline.lua:119
end -- ./candran/cmdline.lua:119
end -- ./candran/cmdline.lua:119
if # missing > 0 then -- ./candran/cmdline.lua:121
return commonerror("missing parameters: " .. tconcat(missing, ", ")) -- ./candran/cmdline.lua:122
end -- ./candran/cmdline.lua:122
end -- ./candran/cmdline.lua:122
return t_out -- ./candran/cmdline.lua:125
end -- ./candran/cmdline.lua:125
end -- ./candran/cmdline.lua:125
local cmdline = _() or cmdline -- ./candran/cmdline.lua:130
package["loaded"]["candran.cmdline"] = cmdline or true -- ./candran/cmdline.lua:131
local function _() -- ./candran/cmdline.lua:134
local candran = require("candran") -- ./candran/util.can:1
local util = {} -- ./candran/util.can:2
util["search"] = function(modpath, exts) -- ./candran/util.can:4
if exts == nil then exts = {} end -- ./candran/util.can:4
for _, ext in ipairs(exts) do -- ./candran/util.can:5
for path in package["path"]:gmatch("[^;]+") do -- ./candran/util.can:6
local fpath = path:gsub("%.lua", "." .. ext):gsub("%?", (modpath:gsub("%.", "/"))) -- ./candran/util.can:7
local f = io["open"](fpath) -- ./candran/util.can:8
if f then -- ./candran/util.can:9
f:close() -- ./candran/util.can:10
return fpath -- ./candran/util.can:11
end -- ./candran/util.can:11
end -- ./candran/util.can:11
end -- ./candran/util.can:11
end -- ./candran/util.can:11
util["load"] = function(str, name, env) -- ./candran/util.can:17
if _VERSION == "Lua 5.1" then -- ./candran/util.can:18
local fn, err = loadstring(str, name) -- ./candran/util.can:19
if not fn then -- ./candran/util.can:20
return fn, err -- ./candran/util.can:20
end -- ./candran/util.can:20
return env ~= nil and setfenv(fn, env) or fn -- ./candran/util.can:21
else -- ./candran/util.can:21
if env then -- ./candran/util.can:23
return load(str, name, nil, env) -- ./candran/util.can:24
else -- ./candran/util.can:24
return load(str, name) -- ./candran/util.can:26
end -- ./candran/util.can:26
end -- ./candran/util.can:26
end -- ./candran/util.can:26
util["recmerge"] = function(...) -- ./candran/util.can:31
local r = {} -- ./candran/util.can:32
for _, t in ipairs({ ... }) do -- ./candran/util.can:33
for k, v in pairs(t) do -- ./candran/util.can:34
if type(v) == "table" then -- ./candran/util.can:35
r[k] = util["merge"](v, r[k]) -- ./candran/util.can:36
else -- ./candran/util.can:36
r[k] = v -- ./candran/util.can:38
end -- ./candran/util.can:38
end -- ./candran/util.can:38
end -- ./candran/util.can:38
return r -- ./candran/util.can:42
end -- ./candran/util.can:42
util["merge"] = function(...) -- ./candran/util.can:45
local r = {} -- ./candran/util.can:46
for _, t in ipairs({ ... }) do -- ./candran/util.can:47
for k, v in pairs(t) do -- ./candran/util.can:48
r[k] = v -- ./candran/util.can:49
end -- ./candran/util.can:49
end -- ./candran/util.can:49
return r -- ./candran/util.can:52
end -- ./candran/util.can:52
util["cli"] = { -- ./candran/util.can:55
["addCandranOptions"] = function(parser) -- ./candran/util.can:57
parser:group("Compiler options", parser:option("-t --target"):description("Target Lua version: lua54, lua53, lua52, luajit or lua51"):default(candran["default"]["target"]), parser:option("--indentation"):description("Character(s) used for indentation in the compiled file"):default(candran["default"]["indentation"]), parser:option("--newline"):description("Character(s) used for newlines in the compiled file"):default(candran["default"]["newline"]), parser:option("--variable-prefix"):description("Prefix used when Candran needs to set a local variable to provide some functionality"):default(candran["default"]["variablePrefix"]), parser:flag("--no-map-lines"):description("Do not add comments at the end of each line indicating the associated source line and file (error rewriting will not work)")) -- ./candran/util.can:76
parser:group("Preprocessor options", parser:flag("--no-builtin-macros"):description("Disable built-in macros"), parser:option("-D --define"):description("Define a preprocessor constant"):args("1-2"):argname({ -- ./candran/util.can:86
"name", -- ./candran/util.can:86
"value" -- ./candran/util.can:86
}):count("*")) -- ./candran/util.can:87
parser:option("--chunkname"):description("Chunkname used when running the code") -- ./candran/util.can:91
parser:flag("--no-rewrite-errors"):description("Disable error rewriting when running the code") -- ./candran/util.can:94
end, -- ./candran/util.can:94
["makeCandranOptions"] = function(args) -- ./candran/util.can:98
local preprocessorEnv = {} -- ./candran/util.can:99
for _, o in ipairs(args["define"]) do -- ./candran/util.can:100
preprocessorEnv[o[1]] = tonumber(o[2]) or o[2] or true -- ./candran/util.can:101
end -- ./candran/util.can:101
local options = { -- ./candran/util.can:104
["target"] = args["target"], -- ./candran/util.can:105
["indentation"] = args["indentation"], -- ./candran/util.can:106
["newline"] = args["newline"], -- ./candran/util.can:107
["variablePrefix"] = args["variable_prefix"], -- ./candran/util.can:108
["mapLines"] = not args["no_map_lines"], -- ./candran/util.can:109
["chunkname"] = args["chunkname"], -- ./candran/util.can:110
["rewriteErrors"] = not args["no_rewrite_errors"], -- ./candran/util.can:111
["builtInMacros"] = not args["no_builtin_macros"], -- ./candran/util.can:112
["preprocessorEnv"] = preprocessorEnv -- ./candran/util.can:113
} -- ./candran/util.can:113
return options -- ./candran/util.can:115
end -- ./candran/util.can:115
} -- ./candran/util.can:115
return util -- ./candran/util.can:119
end -- ./candran/util.can:119
local util = _() or util -- ./candran/util.can:123
package["loaded"]["candran.util"] = util or true -- ./candran/util.can:124
local function _() -- ./candran/util.can:127
local n, v = "serpent", "0.302" -- ./candran/serpent.lua:24
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer" -- ./candran/serpent.lua:25
local snum = { -- ./candran/serpent.lua:26
@ -7067,19 +7010,20 @@ return parser -- ./candran/can-parser/parser.lua:807
end -- ./candran/can-parser/parser.lua:807
local parser = _() or parser -- ./candran/can-parser/parser.lua:811
package["loaded"]["candran.can-parser.parser"] = parser or true -- ./candran/can-parser/parser.lua:812
local unpack = unpack or table["unpack"] -- candran.can:16
local candran = { ["VERSION"] = "0.14.0" } -- candran.can:19
package["loaded"]["candran"] = candran -- candran.can:21
candran["default"] = { -- candran.can:24
["target"] = "lua54", -- candran.can:25
["indentation"] = "", -- candran.can:26
local unpack = unpack or table["unpack"] -- candran.can:15
local candran = { ["VERSION"] = "0.14.0" } -- candran.can:18
package["loaded"]["candran"] = candran -- candran.can:20
candran["default"] = { -- candran.can:23
["target"] = "lua54", -- candran.can:24
["indentation"] = "", -- candran.can:25
["newline"] = "\
", -- candran.can:27
["variablePrefix"] = "__CAN_", -- candran.can:28
["mapLines"] = true, -- candran.can:29
["chunkname"] = "nil", -- candran.can:30
["rewriteErrors"] = true, -- candran.can:31
["noBuiltInMacros"] = false -- candran.can:32
", -- candran.can:26
["variablePrefix"] = "__CAN_", -- candran.can:27
["mapLines"] = true, -- candran.can:28
["chunkname"] = "nil", -- candran.can:29
["rewriteErrors"] = true, -- candran.can:30
["builtInMacros"] = true, -- candran.can:31
["preprocessorEnv"] = {} -- candran.can:32
} -- candran.can:32
if _VERSION == "Lua 5.1" then -- candran.can:36
if package["loaded"]["jit"] then -- candran.can:37
@ -7132,7 +7076,7 @@ end -- candran.can:88
end -- candran.can:88
end -- candran.can:88
preprocessor = preprocessor .. ("return output") -- candran.can:92
local env = util["merge"](_G, options) -- candran.can:95
local env = util["merge"](_G, options["preprocessorEnv"]) -- candran.can:95
env["candran"] = candran -- candran.can:97
env["output"] = "" -- candran.can:99
env["import"] = function(modpath, margs) -- candran.can:106
@ -7207,7 +7151,7 @@ else -- candran.can:175
error(("invalid macro type %s"):format(tostring(iast["tag"]))) -- candran.can:177
end -- candran.can:177
end -- candran.can:177
if not options["noBuiltInMacros"] then -- candran.can:182
if options["builtInMacros"] then -- candran.can:182
env["define"]("__STR__(x)", function(x) -- candran.can:183
return ("%q"):format(x) -- candran.can:183
end) -- candran.can:183

View file

@ -1,126 +0,0 @@
-- started: 2008-04-12 by Shmuel Zeigerman
-- license: public domain
local ipairs,pairs,setfenv,tonumber,loadstring,type =
ipairs,pairs,setfenv,tonumber,loadstring,type
local tinsert, tconcat = table.insert, table.concat
local function commonerror (msg)
return nil, ("[cmdline]: " .. msg)
end
local function argerror (msg, numarg)
msg = msg and (": " .. msg) or ""
return nil, ("[cmdline]: bad argument #" .. numarg .. msg)
end
local function iderror (numarg)
return argerror("ID not valid", numarg)
end
local function idcheck (id)
return id:match("^[%a_][%w_]*$") and true
end
--[[------------------------------------------------------------------------
Syntax:
t_out = getparam(t_in [,options] [,params])
Parameters:
t_in: table - list of string arguments to be processed in order
(usually it is the `arg' table created by the Lua interpreter).
* if an argument begins with $, the $ is skipped and the rest is inserted
into the array part of the output table.
* if an argument begins with -, the rest is a sequence of variables
(separated by commas or semicolons) that are all set to true;
example: -var1,var2 --> var1,var2 = true,true
* if an argument begins with !, the rest is a Lua chunk;
example: !a=(40+3)*5;b=20;name="John";window={w=600,h=480}
* if an argument contains =, then it is an assignment in the form
var1,...=value (no space is allowed around the =)
* if value begins with $, the $ is skipped, the rest is a string
example: var1,var2=$ --> var1,var2 = "",""
example: var1,var2=$125 --> var1,var2 = "125","125"
example: var1,var2=$$125 --> var1,var2 = "$125","$125"
* if value is convertible to number, it is a number
example: var1,var2=125 --> var1,var2 = 125,125
* if value is true of false, it is a boolean
example: var1=false --> var1 = false
* otherwise it is a string
example: name=John --> name = "John"
* if an argument neither begins with one of the special characters (-,!,$),
nor contains =, it is inserted as is into the array part of the output
table.
options (optional): a list of names of all command-line options and parameters
permitted in the application; used to check that each found option
is valid; no checks are done if not supplied.
params (optional): a list of names of all command-line parameters required
by the application; used to check that each required parameter is present;
no checks are done if not supplied.
Returns:
On success: the output table, e.g. { [1]="./myfile.txt", name="John", age=40 }
On error: nil followed by error message string.
--]]------------------------------------------------------------------------
return function(t_in, options, params)
local t_out = {}
for i,v in ipairs(t_in) do
local prefix, command = v:sub(1,1), v:sub(2)
if prefix == "$" then
tinsert(t_out, command)
elseif prefix == "-" then
for id in command:gmatch"[^,;]+" do
if not idcheck(id) then return iderror(i) end
t_out[id] = true
end
elseif prefix == "!" then
local f, err = loadstring(command)
if not f then return argerror(err, i) end
setfenv(f, t_out)()
elseif v:find("=") then
local ids, val = v:match("^([^=]+)%=(.*)") -- no space around =
if not ids then return argerror("invalid assignment syntax", i) end
if val == "false" then
val = false
elseif val == "true" then
val = true
else
val = val:sub(1,1)=="$" and val:sub(2) or tonumber(val) or val
end
for id in ids:gmatch"[^,;]+" do
if not idcheck(id) then return iderror(i) end
t_out[id] = val
end
else
tinsert(t_out, v)
end
end
if options then
local lookup, unknown = {}, {}
for _,v in ipairs(options) do lookup[v] = true end
for k,_ in pairs(t_out) do
if lookup[k]==nil and type(k)=="string" then tinsert(unknown, k) end
end
if #unknown > 0 then
return commonerror("unknown options: " .. tconcat(unknown, ", "))
end
end
if params then
local missing = {}
for _,v in ipairs(params) do
if t_out[v]==nil then tinsert(missing, v) end
end
if #missing > 0 then
return commonerror("missing parameters: " .. tconcat(missing, ", "))
end
end
return t_out
end

View file

@ -1,3 +1,4 @@
local candran = require("candran")
local util = {}
function util.search(modpath, exts={})
@ -51,4 +52,68 @@ function util.merge(...)
return r
end
util.cli = {
-- add option to set Candran options to an argparse parser
addCandranOptions = function(parser)
parser:group("Compiler options",
parser:option("-t --target")
:description "Target Lua version: lua54, lua53, lua52, luajit or lua51"
:default(candran.default.target),
parser:option("--indentation")
:description "Character(s) used for indentation in the compiled file"
:default(candran.default.indentation),
parser:option("--newline")
:description "Character(s) used for newlines in the compiled file"
:default(candran.default.newline),
parser:option("--variable-prefix")
:description "Prefix used when Candran needs to set a local variable to provide some functionality"
:default(candran.default.variablePrefix),
parser:flag("--no-map-lines")
:description "Do not add comments at the end of each line indicating the associated source line and file (error rewriting will not work)"
)
parser:group("Preprocessor options",
parser:flag("--no-builtin-macros")
:description "Disable built-in macros",
parser:option("-D --define")
:description "Define a preprocessor constant"
:args("1-2")
:argname{"name", "value"}
:count("*")
)
parser:option("--chunkname")
:description "Chunkname used when running the code"
parser:flag("--no-rewrite-errors")
:description "Disable error rewriting when running the code"
end,
-- convert parsed arguments to a Candran options table
makeCandranOptions = function(args)
local preprocessorEnv = {}
for _, o in ipairs(args.define) do
preprocessorEnv[o[1]] = tonumber(o[2]) or o[2] or true
end
local options = {
target = args.target,
indentation = args.indentation,
newline = args.newline,
variablePrefix = args.variable_prefix,
mapLines = not args.no_map_lines,
chunkname = args.chunkname,
rewriteErrors = not args.no_rewrite_errors,
builtInMacros = not args.no_builtin_macros,
preprocessorEnv = preprocessorEnv
}
return options
end
}
return util

View file

@ -18,14 +18,16 @@ description = {
}
source = {
url = "git://github.com/Reuh/candran"
url = "git://github.com/Reuh/candran",
branch = "argparse"
}
dependencies = {
"lua >= 5.1",
"lpeglabel >= 1.5.0",
"linenoise >= 0.9",
"luacheck >= 0.23.0"
"luacheck >= 0.23.0",
"argparse >= 0.7.0"
}
build = {