Skip to content

Commit f9f5477

Browse files
committed
Implement the rest of the parsing
1 parent dc10532 commit f9f5477

File tree

1 file changed

+83
-19
lines changed

1 file changed

+83
-19
lines changed

src/luasm.lua

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,57 @@ function Tokenizer:get_mnemonic()
150150
return mnemonic
151151
end
152152

153+
local ArgumentTokenizer = {}
154+
155+
function ArgumentTokenizer:get_next(argument_type)
156+
local argument_regex = self.luasm.settings.syntax[argument_type]
157+
158+
local matched = self.line:match(argument_regex, self.position)
159+
160+
if matched ~= nil then
161+
self.position = self.position + matched:len()
162+
end
163+
164+
return matched
165+
end
166+
167+
function ArgumentTokenizer:skip_separator()
168+
local matched = self.line:match(self.luasm.settings.separator, self.position)
169+
170+
if matched == nil then
171+
return false
172+
end
173+
174+
self.position = self.position + matched:len()
175+
176+
return true
177+
end
178+
179+
function ArgumentTokenizer:reset()
180+
self.position = 1
181+
end
182+
183+
function ArgumentTokenizer:eol()
184+
return self.position > self.line:len()
185+
end
186+
187+
--- Creates an argument tokenizer based upon the current state
188+
--- of the creating tokenizer.
189+
---
190+
--- @return table The argument tokenizer
191+
function Tokenizer:argument_tokenizer()
192+
local obj = {}
193+
194+
obj.line = self.line
195+
obj.luasm = self.luasm
196+
obj.position = 1
197+
198+
setmetatable(obj, ArgumentTokenizer)
199+
ArgumentTokenizer.__index = ArgumentTokenizer
200+
201+
return obj
202+
end
203+
153204
--- Creates a new tokenizer without a specific implementation.
154205
--- @return table A tokenizer instance (needs a concrete `get_next_line` implementation).
155206
function Tokenizer:new(luasm)
@@ -220,37 +271,46 @@ end
220271
--- `{ op = opcode, args = args, line = current line }`
221272
---
222273
--- If the parsing has errored out, it returns a string with the error message.
223-
--- @param elements table Token list where `elements[1]` is the mnemonic.
224-
--- @param luasm table The LuASM instance (provides settings, etc.).
274+
--- @param arguments table Token list where `elements[1]` is the mnemonic.
275+
--- @param luasm table The LuASM instance (provides settings, etc.).
225276
--- @return table|string On success a table `{op, args, line, run}`; on failure a string error message.
226-
function instruction:parse(elements, luasm)
277+
function instruction:parse(arguments, luasm)
227278
-- `elements[1]` is the mnemonic, the rest are raw operands
228279
local opcode = self.name
229280
local expected = self.structure -- e.g. {"imm","reg"}
230281

231-
if #elements - 1 ~= #expected then
232-
local err = string.format(
233-
"Wrong number of operands for %s (expected %d, got %d)",
234-
opcode, #expected, #elements - 1)
235-
return err
236-
end
237282

238283
local args = {}
239-
for i = 2, #elements do
240-
local pattern = luasm.settings.syntax[expected[i - 1]]
241-
if pattern == nil then
242-
error("The pattern with the name of '" .. expected[i - 1] .. "' does not exist.", 2)
243-
return "Pattern not found"
284+
for index, value in ipairs(expected) do
285+
if index ~= 1 then
286+
if not arguments:skip_separator() then
287+
local err = string.format(
288+
"Expected separator after the argument number %d (for %s)",
289+
index - 1, opcode
290+
)
291+
return err
292+
end
244293
end
245294

246-
local arg = elements[i]:match(pattern)
295+
local arg = arguments:get_next(value)
296+
247297
if arg == nil then
248298
local err = string.format(
249-
"Could not match argument '%s' (expected %s)",
250-
elements[i], expected[i - 1])
299+
"Wrong number of operands for %s (expected %d but got less)",
300+
opcode, #expected
301+
)
251302
return err
252303
end
253-
args[i - 1] = arg
304+
305+
args[#args + 1] = arg
306+
end
307+
308+
if not arguments:eol() then
309+
local err = string.format(
310+
"Wrong number of operands for %s (expected %d but got more)",
311+
opcode, #expected
312+
)
313+
return err
254314
end
255315

256316
return {
@@ -304,12 +364,16 @@ function LuASM:parse(tokenizer)
304364
local mnemonic = tokenizer:get_mnemonic()
305365

306366
local errors = {}
367+
local argument_tokenizer = tokenizer:argument_tokenizer()
368+
307369
for _, instr in ipairs(self.instructions) do
308370
if instr.name ~= mnemonic then
309371
goto inner
310372
end
311373

312-
local result = instr:parse(tokenizer, self)
374+
local result = instr:parse(argument_tokenizer, self)
375+
argument_tokenizer:reset()
376+
313377
if type(result) == "table" then
314378
parse_data.instructions[#parse_data.instructions + 1] = result
315379
goto continue -- go to the outer `continue` label

0 commit comments

Comments
 (0)