]> git.lizzy.rs Git - metalua.git/blobdiff - src/compiler/mlp_stat.lua
improved messages clarity, following suggestions by D. Manura
[metalua.git] / src / compiler / mlp_stat.lua
index a77a395f26c5a3ff7086bcc8993b5b16b16f2b6f..282954edcb3231748a0d3ed305ea1808355208d0 100644 (file)
@@ -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 <expr_list>" 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 "<list>")
+         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 "<list>".."'" 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 <name> <func_val>
    { "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 <id_list> ( = <expr_list> )?
    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