diff options
author | Aki <please@ignore.pl> | 2024-06-30 23:50:21 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2024-06-30 23:50:21 +0200 |
commit | d6189e60851ff347c8c11812025232621f54096e (patch) | |
tree | 0c1694b98a80ef4dd4c0f04ee11ae62c4562d818 | |
parent | e2690e1cce87be317dd8169e93a59318b42e3b82 (diff) | |
download | headers-d6189e60851ff347c8c11812025232621f54096e.zip headers-d6189e60851ff347c8c11812025232621f54096e.tar.gz headers-d6189e60851ff347c8c11812025232621f54096e.tar.bz2 |
Split "DSL" definition from the "all-in-parser-and-output"
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | db/c.lua | 1 | ||||
-rw-r--r-- | db/posix.lua | 1 | ||||
-rwxr-xr-x | headers.lua | 141 | ||||
-rw-r--r-- | headers/definition.lua | 49 | ||||
-rw-r--r-- | headers/parser.lua | 123 | ||||
-rw-r--r-- | spec/parser_spec.lua | 16 |
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 @@ -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) |