X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcompiler%2Fmlp_stat.lua;h=282954edcb3231748a0d3ed305ea1808355208d0;hb=f89b6df86fd333a51edd544bd975069c206067a9;hp=a77a395f26c5a3ff7086bcc8993b5b16b16f2b6f;hpb=82ad5bb5a31774faed5a813700572235b29c7730;p=metalua.git diff --git a/src/compiler/mlp_stat.lua b/src/compiler/mlp_stat.lua index a77a395..282954e 100644 --- a/src/compiler/mlp_stat.lua +++ b/src/compiler/mlp_stat.lua @@ -54,6 +54,7 @@ block = gg.list { name = "statements block", terminators = block_terminators, primary = function (lx) + -- FIXME use gg.optkeyword() local x = stat (lx) if lx:is_keyword (lx:peek(), ";") then lx:next() end return x @@ -61,10 +62,17 @@ block = gg.list { -------------------------------------------------------------------------------- -- Helper function for "return " parsing. --- Called when parsing return statements +-- Called when parsing return statements. +-- The specific test for initial ";" is because it's not a block terminator, +-- so without itgg.list would choke on "return ;" statements. +-- We don't make a modified copy of block_terminators because this list +-- is sometimes modified at runtime, and the return parser would get out of +-- sync if it was relying on a copy. -------------------------------------------------------------------------------- -local return_expr_list_parser = gg.list { - expr, separators = ",", terminators = block_terminators } +local return_expr_list_parser = gg.multisequence{ + { ";" , builder = function() return { } end }, + default = gg.list { + expr, separators = ",", terminators = block_terminators } } -------------------------------------------------------------------------------- -- for header, between [for] and [do] (exclusive). @@ -81,7 +89,7 @@ function for_header (lx) else -- Forin: there might be several vars local a = lx:is_keyword (lx:next(), ",", "in") - if a=="in" then var_list = { var } else + if a=="in" then var_list = { var, lineinfo = var.lineinfo } else -- several vars; first "," skipped, read other vars var_list = gg.list{ primary = id, separators = ",", terminators = "in" } (lx) @@ -115,10 +123,15 @@ local method_name = gg.onkeyword{ name = "method invocation", ":", id, local function funcdef_builder(x) local name, method, func = x[1], x[2], x[3] if method then - name = { tag="Index", name, method } + name = { tag="Index", name, method, lineinfo = { + first = name.lineinfo.first, + last = method.lineinfo.last } } _G.table.insert (func[1], 1, {tag="Id", "self"}) end - return { tag="Set", {name}, {func} } + local r = { tag="Set", {name}, {func} } + r[1].lineinfo = name.lineinfo + r[2].lineinfo = func.lineinfo + return r end @@ -156,20 +169,31 @@ local function assign_or_call_stat_parser (lx) else assert (#e > 0) if #e > 1 then - gg.parse_error (lx, "comma is not a valid statement separator") end + gg.parse_error (lx, + "comma is not a valid statement separator; statement can be ".. + "separated by semicolons, or not separated at all") end if e[1].tag ~= "Call" and e[1].tag ~= "Invoke" then - gg.parse_error (lx, "This expression is of type '%s'; ".. - "only function and method calls make valid statements", - e[1].tag or "") + local typename + if e[1].tag == 'Id' then typename = "an identifier" + elseif e[1].tag == 'Op' then typename = "an arithmetic operation" + else typename = "of type '"..(e[1].tag or "".."'" end + + gg.parse_error (lx, "This expression is " .. typename .. + "; only function and method call expressions ".. + "can be used as statements"); end return e[1] end end -local local_stat_parser = gg.multisequence{ +local_stat_parser = gg.multisequence{ -- local function { "function", id, func_val, builder = - function(x) return { tag="Localrec", { x[1] }, { x[2] } } end }, + function(x) + local vars = { x[1], lineinfo = x[1].lineinfo } + local vals = { x[2], lineinfo = x[2].lineinfo } + return { tag="Localrec", vars, vals } + end }, -- local ( = )? default = gg.sequence{ id_list, gg.onkeyword{ "=", expr_list }, builder = function(x) return {tag="Local", x[1], x[2] or { } } end } } @@ -197,4 +221,4 @@ stat = gg.multisequence { stat.assignments = { ["="] = "Set" } -function stat.assignments:add(k, v) self[k] = v end \ No newline at end of file +function stat.assignments:add(k, v) self[k] = v end