about summary refs log tree commit diff stats
path: root/port.lua
diff options
context:
space:
mode:
authorCase Duckworth2024-04-09 21:04:17 -0500
committerCase Duckworth2024-04-09 21:04:29 -0500
commit8ce2915e3c54598c2fda4fec0980ebfc2a3adf6e (patch)
tree124ef31663ed570bed358dffd9c861d10fabce7b /port.lua
parentUh (diff)
downloadlam-8ce2915e3c54598c2fda4fec0980ebfc2a3adf6e.tar.gz
lam-8ce2915e3c54598c2fda4fec0980ebfc2a3adf6e.zip
Reorganization
Diffstat (limited to 'port.lua')
-rw-r--r--port.lua103
1 files changed, 103 insertions, 0 deletions
diff --git a/port.lua b/port.lua new file mode 100644 index 0000000..812f05e --- /dev/null +++ b/port.lua
@@ -0,0 +1,103 @@
1--- lam.port --- port objects
2-- because the implementation for ports is fairly involved, they're in their own
3-- file outside of `type'.
4
5local m = {}
6local util = require("util")
7local error = util.error
8local tochars = util.tochars
9
10-- The EOF object is what the reader emits when it hits an end-of-file or use up
11-- a port.
12m.eof = setmetatable({}, {
13 __type = "eof",
14 __tostring = function () return "#<eof>" end,
15})
16
17---[[ INPUT PORTS ]]---
18
19-- return the next token from PORT, given READTABLE
20local function input_port_next_token (port, readtable)
21 repeat
22 if #port.buffer == 0 then
23 if port.file then
24 local ln = port.file:read()
25 if ln == nil then
26 return m.eof
27 end
28 port.buffer = tochars(ln)
29 else
30 return m.eof
31 end
32 end
33
34 local token, token_type
35 local c = port.buffer[1]
36 if readtable.chars[c] then
37 token, token_type, port.buffer =
38 readtable.chars[c](port.buffer)
39 else
40 for re, fn in pairs(readtable.regex) do
41 if c:match(re) then
42 token, token_type, port.buffer =
43 fn(port.buffer)
44 break
45 end
46 end
47 if token == nil then
48 token, token_type, port.buffer =
49 readtable.default(port.buffer)
50 end
51 end
52
53 port.buffer = port.buffer or {}
54 if token then
55 return token, token_type
56 end
57 until nil
58end
59
60function m.input_port (source, source_type)
61 -- SOURCE is the name of the file/string to read or nil; nil means
62 -- standard input. SOURCE_TYPE is one of "file", "string"; "file" is
63 -- the default.
64 local f, b
65 source_type = source_type or "file"
66 if source then
67 if source_type == "file" then
68 f = io.open(source, "r")
69 elseif source_type == "string" then
70 b = tochars(source)
71 else
72 error("input-port: bad type", source_type)
73 end
74 else
75 f = io.input() -- ignore SOURCE_TYPE
76 end
77 local t = {
78 file = f,
79 name = f and source or "[string]",
80 type = source_type,
81 buffer = b or {},
82 flush = function (self) self.buffer = {} end,
83 next = input_port_next_token, -- port:next(readtable)
84 close =
85 function (self)
86 if self.file then self.file:close() end
87 end,
88 }
89 local mt = {
90 __type = "input-port",
91 __tostring =
92 function (self)
93 return string.format("#<port %s>", self.name)
94 end,
95 }
96 return setmetatable(t, mt)
97end
98
99---[[ OUTPUT PORTS ]]---
100-- TODO
101
102--------
103return m