summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2024-06-30 23:50:21 +0200
committerAki <please@ignore.pl>2024-06-30 23:50:21 +0200
commitd6189e60851ff347c8c11812025232621f54096e (patch)
tree0c1694b98a80ef4dd4c0f04ee11ae62c4562d818
parente2690e1cce87be317dd8169e93a59318b42e3b82 (diff)
downloadheaders-d6189e60851ff347c8c11812025232621f54096e.zip
headers-d6189e60851ff347c8c11812025232621f54096e.tar.gz
headers-d6189e60851ff347c8c11812025232621f54096e.tar.bz2
Split "DSL" definition from the "all-in-parser-and-output"
-rw-r--r--Makefile6
-rw-r--r--db/c.lua1
-rw-r--r--db/posix.lua1
-rwxr-xr-xheaders.lua141
-rw-r--r--headers/definition.lua49
-rw-r--r--headers/parser.lua123
-rw-r--r--spec/parser_spec.lua16
7 files changed, 210 insertions, 127 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..28eceec
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+all: test
+
+test:
+ busted
+
+.PHONY: all test
diff --git a/db/c.lua b/db/c.lua
index adc6bd7..c2d10e5 100644
--- a/db/c.lua
+++ b/db/c.lua
@@ -1,3 +1,4 @@
+scheme "headers/1"
aliases "ISO/IEC 9899:1990" {"ANSI X3.159-1989", "C89", "C90", "ANSI C"}
aliases "ISO/IEC 9899:1990/Amd 1:1995" {"C95"}
aliases "ISO/IEC 9899:1999" {"C99"}
diff --git a/db/posix.lua b/db/posix.lua
index 3757a7d..467294c 100644
--- a/db/posix.lua
+++ b/db/posix.lua
@@ -1,3 +1,4 @@
+scheme "headers/1"
aliases "IEEE Std 1003.1-2008" {"POSIX"}
headers "POSIX" {
"aio.h",
diff --git a/headers.lua b/headers.lua
index 13d98a9..972b360 100755
--- a/headers.lua
+++ b/headers.lua
@@ -1,130 +1,17 @@
#!/usr/bin/env lua
---- For example:
----
---- $ ./headers.lua db/c.lua C23
---- assert.h
---- ctype.h
---- ...
-local public = {}
-local private = {}
-private.tags = {}
-private.tags_lookup = {}
-private.headers = {}
-
-
-local tag do
- local methods = {}
- function methods:add (header)
- table.insert(self.headers_, header)
- end
- local function headers (self)
- local result = {}
- for _, value in pairs(self.headers_) do
- if type(value) == "function" then
- value(result)
- else
- table.insert(result, value)
- end
- end
- return result
- end
- local mt = {
- __tostring=function (self) return self.name end,
- __index=function (self, key)
- if key == "headers" then
- return headers(self)
- end
- return methods[key]
- end,
- }
- function tag (name)
- return setmetatable({name=name, headers_={}}, mt)
- end
-end
-
-
-local alias do
- local mt = {
- __tostring = function (self) return string.format("%s (%s)", self.name, tostring(self.tag)) end,
- __index = function (self, key) return self.tag[key] end,
- }
- function alias (name, tag)
- return setmetatable({name=name, tag=tag}, mt)
- end
-end
-
-
-local function include (source)
- return function (target)
- for _, header in pairs(source.headers) do
- table.insert(target, header)
- end
- end
-end
-
-
-local function remove (header)
- return function (target)
- for key, value in pairs(target) do
- if value == header then
- table.remove(target, key)
- end
- end
- end
-end
-
-
-local function get_or_create_tag (name)
- local found = private.tags_lookup[name]
- if not found then
- found = tag(name)
- table.insert(private.tags, found)
- private.tags_lookup[name] = found
- end
- return found
-end
-
-
-function public.aliases (name)
- local tag = get_or_create_tag(name)
- return function (aliases)
- for _, name in pairs(aliases) do
- private.tags_lookup[name] = alias(name, tag)
- end
- end
-end
-
-
-function public.headers (name)
- local tag = get_or_create_tag(name)
- return function (filenames)
- for _, header in pairs(filenames) do
- tag:add(header)
- end
- end
-end
-
-
-function public.include (tag)
- tag = private.tags_lookup[tag] or error("invalid tag: " .. tag, 2)
- return include(tag)
-end
-
-
-function public.remove (header)
- return remove(header)
-end
-
-
-local db = loadfile(arg[1], nil, public)
-db()
-if arg[2] then
- local tag = private.tags_lookup[arg[2]]
- for _, header in pairs(tag.headers) do
- print(header)
- end
-else
- for _, tag in pairs(private.tags_lookup) do
- print(tag)
+local args = require "pl.lapp" [[
+Prints list of headers from a standard or available standards
+ -d (string default 'db/') Directory where definitions are placed
+ <selection> (optional string) Standard to display headers for
+]]
+local dir = require "pl.dir"
+local parse = require "headers.parser"
+local definitions = dir.getfiles(args.d, "*.lua")
+for _, filename in pairs(definitions) do
+ local handle = io.open(filename)
+ local data = handle:read("a")
+ handle:close()
+ if parse(data, args.selection) then
+ return -- interface is yet to be properly defined, this allows only for first-result queries
end
end
diff --git a/headers/definition.lua b/headers/definition.lua
new file mode 100644
index 0000000..82ce3b5
--- /dev/null
+++ b/headers/definition.lua
@@ -0,0 +1,49 @@
+--- Builds a definition parser that binds to a *private* object that implements +3,+41/private:/ callbacks.
+local
+function build (private)
+ local public = {}
+
+ --- scheme "headers/1"
+ function public.scheme (identifier)
+ if identifier ~= "headers/1" then
+ error("unknown scheme: " .. identifier, 2)
+ end
+ end
+
+ --- aliases "Formal Name" {"FN"}
+ --- aliases "New Formal Name" {"FN42"}
+ function public.aliases (tag)
+ tag = private:get_or_add_tag(tag)
+ return function (others)
+ for _, other in pairs(others) do
+ private:add_alias(tag, other)
+ end
+ end
+ end
+
+ --- headers "FN" {"a.fn", "b.fn"}
+ function public.headers (tag)
+ tag = private:get_or_add_tag(tag)
+ return function (entries)
+ for _, entry in pairs(entries) do
+ private:add_entry(tag, entry)
+ end
+ end
+ end
+
+ --- headers "FN42" {include "FN"}
+ function public.include (tag)
+ tag = private:get_tag(tag) or error("tag not found: " .. tag, 2)
+ return private:create_include(tag)
+ end
+
+ --- headers "FN42" {remove "a.fn"}
+ function public.remove (header)
+ return private:create_remove(header)
+ end
+
+ return public
+end
+
+
+return build
diff --git a/headers/parser.lua b/headers/parser.lua
new file mode 100644
index 0000000..e6895e6
--- /dev/null
+++ b/headers/parser.lua
@@ -0,0 +1,123 @@
+local build_definition = require "headers.definition"
+
+
+local tag do
+ local methods = {}
+ function methods:add (header)
+ table.insert(self.headers_, header)
+ return header
+ end
+ local function headers (self)
+ local result = {}
+ for _, value in pairs(self.headers_) do
+ if type(value) == "function" then
+ value(result)
+ else
+ table.insert(result, value)
+ end
+ end
+ return result
+ end
+ local mt = {
+ __tostring=function (self) return self.name end,
+ __index=function (self, key)
+ if key == "headers" then
+ return headers(self)
+ end
+ return methods[key]
+ end,
+ }
+ function tag (name)
+ return setmetatable({name=name, headers_={}}, mt)
+ end
+end
+
+
+local alias do
+ local mt = {
+ __tostring = function (self) return string.format("%s\t(%s)", self.name, tostring(self.tag)) end,
+ __index = function (self, key) return self.tag[key] end,
+ }
+ function alias (name, tag)
+ return setmetatable({name=name, tag=tag}, mt)
+ end
+end
+
+
+local private = {}
+private.tags = {}
+private.tag_lookup = {}
+
+
+function private:get_or_add_tag (name)
+ local found = self:get_tag(name)
+ if not found then
+ found = tag(name)
+ table.insert(self.tags, found)
+ self.tag_lookup[name] = found
+ end
+ return found
+end
+
+
+function private:get_tag (name)
+ return self.tag_lookup[name]
+end
+
+
+function private:add_alias (tag, name)
+ self.tag_lookup[name] = alias(name, tag)
+ return self.tag_lookup[name]
+end
+
+
+function private:add_entry (tag, entry)
+ return tag:add(entry)
+end
+
+
+function private:create_include (source)
+ return function (target)
+ for _, header in pairs(source.headers) do
+ table.insert(target, header)
+ end
+ end
+end
+
+
+function private:create_remove (header)
+ return function (target)
+ for key, value in pairs(target) do
+ if value == header then
+ table.remove(target, key)
+ end
+ end
+ end
+end
+
+
+function private:reset ()
+ self.tags = {}
+ self.tag_lookup = {}
+end
+
+
+return function (input, selection)
+ private:reset() -- interface yet to be defined, this is a naive workaround to avoid retriggering prints
+ local db = load(input, nil, nil, build_definition(private))
+ db()
+ if selection then
+ local found = private:get_tag(selection)
+ if not found then
+ return false
+ end
+ for _, header in pairs(found.headers) do
+ print(header)
+ end
+ else
+ for _, tag in pairs(private.tag_lookup) do
+ print(tag)
+ end
+ end
+ return true
+end
diff --git a/spec/parser_spec.lua b/spec/parser_spec.lua
new file mode 100644
index 0000000..78ee8b8
--- /dev/null
+++ b/spec/parser_spec.lua
@@ -0,0 +1,16 @@
+local parse = require "headers.parser"
+
+
+describe("Scheme", function()
+ it("version one is supported", function()
+ assert.has_no.errors(function()
+ parse [[scheme "headers/1"]]
+ end)
+ end)
+
+ it("is not required", function()
+ assert.has_no.errors(function()
+ parse ""
+ end)
+ end)
+end)