--- 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