fy36
2025-07-01 350eb5ec9163d3ea21416b1525bb80191e958071
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
--------------------------------------------------------------------------------
-- Copyright (c) 2006-2013 Fabien Fleutot and others.
--
-- All rights reserved.
--
-- This program and the accompanying materials are made available
-- under the terms of the Eclipse Public License v1.0 which
-- accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- This program and the accompanying materials are also made available
-- under the terms of the MIT public license which accompanies this
-- distribution, and is available at http://www.lua.org/license.html
--
-- Contributors:
--     Fabien Fleutot - API and implementation
--
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
--
-- Exported API:
-- * [M.table_bracket_field()]
-- * [M.table_field()]
-- * [M.table_content()]
-- * [M.table()]
--
-- KNOWN BUG: doesn't handle final ";" or "," before final "}"
--
--------------------------------------------------------------------------------
 
local gg  = require 'metalua.grammar.generator'
 
return function(M)
 
    M.table = { }
    local _table = gg.future(M.table)
    local _expr  = gg.future(M).expr
 
    --------------------------------------------------------------------------------
    -- `[key] = value` table field definition
    --------------------------------------------------------------------------------
    M.table.bracket_pair = gg.sequence{ "[", _expr, "]", "=", _expr, builder = "Pair" }
 
    --------------------------------------------------------------------------------
    -- table element parser: list value, `id = value` pair or `[value] = value` pair.
    --------------------------------------------------------------------------------
    function M.table.element (lx)
        if lx :is_keyword (lx :peek(), "[") then return M.table.bracket_pair(lx) end
        local e = M.expr (lx)
        if not lx :is_keyword (lx :peek(), "=") then return e end
        lx :next(); -- skip the "="
        local ok, key = pcall(M.id2string, e) -- will fail on non-identifiers
        if not ok then return gg.parse_error (lx, "Identifier expected.") end
        local val = M.expr(lx)
        local r = { tag="Pair", key, val }
        r.lineinfo = { first = key.lineinfo.first, last = val.lineinfo.last }
        return r
    end
 
    -----------------------------------------------------------------------------
    -- table constructor, without enclosing braces; returns a full table object
    -----------------------------------------------------------------------------
    M.table.content  = gg.list {
        -- eta expansion to allow patching the element definition
        primary     =  _table.element,
        separators  = { ",", ";" },
        terminators = "}",
        builder     = "Table" }
 
    --------------------------------------------------------------------------------
    -- complete table constructor including [{...}]
    --------------------------------------------------------------------------------
    -- TODO beware, stat and expr use only table.content, this can't be patched.
    M.table.table = gg.sequence{ "{", _table.content, "}", builder = unpack }
 
    return M
end