I tried the approach you suggested above, but ran into problems because any statement like
"i = ..." causes problems because the i is seen as suffix for the previous line/statement. I then tried the option of changing the number lexer. It works quite well. Here is my implementation:
--------------------------------------------------------------------------------
-- Number extractor modified to include complex number notation
--------------------------------------------------------------------------------
function lexer.lexer:extract_number()
-- Number
local imag
local j = self.src:match(self.patterns.number_hex, self.i)
if not j then
j = self.src:match (self.patterns.number_mantissa[1], self.i) or
self.src:match (self.patterns.number_mantissa[2], self.i)
if j then
j = self.src:match (self.patterns.number_exponant, j) or j;
imag = self.src:match ("^[ij]()", j);
end
end
if not j then return end
-- Number found, interpret with tonumber() and return it
local n = tonumber (self.src:sub (self.i, j-1))
if not imag then
self.i = j
return "Number", n
else
self.i = imag
return "Imag", n
end
end
--------------------------------------------------------------------------------
-- Default parser for primary expressions modified to support imaginary numbers
--------------------------------------------------------------------------------
function id_or_literal (lx)
local a = lx:next()
if not (a.tag=="Id" or a.tag=="String" or a.tag=="Number" or a.tag=="Imag") then
local msg
if a.tag=='Eof' then
msg = "End of file reached when an expression was expected"
elseif a.tag=='Keyword' then
msg = "An expression was expected, and `"..a[1]..
"' can't start an expression"
else
msg = "Unexpected expr token " .. _G.table.tostring (a, 'nohash')
end
gg.parse_error (lx, msg)
end
if a.tag=="Imag" then
return {tag="Call", {tag="Id", "complex"}, {tag="Number", 0}, {tag="Number", a[1]}}
else
return a
end
end
-- Replace the default id_or_literal parser with the new one
mlp.expr.primary.default = id_or_literal