From 8ce2915e3c54598c2fda4fec0980ebfc2a3adf6e Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Tue, 9 Apr 2024 21:04:17 -0500 Subject: Reorganization --- port.lua | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 port.lua (limited to 'port.lua') diff --git a/port.lua b/port.lua new file mode 100644 index 0000000..812f05e --- /dev/null +++ b/port.lua @@ -0,0 +1,103 @@ +--- lam.port --- port objects +-- because the implementation for ports is fairly involved, they're in their own +-- file outside of `type'. + +local m = {} +local util = require("util") +local error = util.error +local tochars = util.tochars + +-- The EOF object is what the reader emits when it hits an end-of-file or use up +-- a port. +m.eof = setmetatable({}, { + __type = "eof", + __tostring = function () return "#" end, +}) + +---[[ INPUT PORTS ]]--- + +-- return the next token from PORT, given READTABLE +local function input_port_next_token (port, readtable) + repeat + if #port.buffer == 0 then + if port.file then + local ln = port.file:read() + if ln == nil then + return m.eof + end + port.buffer = tochars(ln) + else + return m.eof + end + end + + local token, token_type + local c = port.buffer[1] + if readtable.chars[c] then + token, token_type, port.buffer = + readtable.chars[c](port.buffer) + else + for re, fn in pairs(readtable.regex) do + if c:match(re) then + token, token_type, port.buffer = + fn(port.buffer) + break + end + end + if token == nil then + token, token_type, port.buffer = + readtable.default(port.buffer) + end + end + + port.buffer = port.buffer or {} + if token then + return token, token_type + end + until nil +end + +function m.input_port (source, source_type) + -- SOURCE is the name of the file/string to read or nil; nil means + -- standard input. SOURCE_TYPE is one of "file", "string"; "file" is + -- the default. + local f, b + source_type = source_type or "file" + if source then + if source_type == "file" then + f = io.open(source, "r") + elseif source_type == "string" then + b = tochars(source) + else + error("input-port: bad type", source_type) + end + else + f = io.input() -- ignore SOURCE_TYPE + end + local t = { + file = f, + name = f and source or "[string]", + type = source_type, + buffer = b or {}, + flush = function (self) self.buffer = {} end, + next = input_port_next_token, -- port:next(readtable) + close = + function (self) + if self.file then self.file:close() end + end, + } + local mt = { + __type = "input-port", + __tostring = + function (self) + return string.format("#", self.name) + end, + } + return setmetatable(t, mt) +end + +---[[ OUTPUT PORTS ]]--- +-- TODO + +-------- +return m -- cgit 1.4.1-21-gabe81