1 -------------------------------------------------------------------------------
2 -- Copyright (c) 2006-2013 Fabien Fleutot and others.
4 -- All rights reserved.
6 -- This program and the accompanying materials are made available
7 -- under the terms of the Eclipse Public License v1.0 which
8 -- accompanies this distribution, and is available at
9 -- http://www.eclipse.org/legal/epl-v10.html
11 -- This program and the accompanying materials are also made available
12 -- under the terms of the MIT public license which accompanies this
13 -- distribution, and is available at http://www.lua.org/license.html
16 -- Fabien Fleutot - API and implementation
18 -------------------------------------------------------------------------------
20 --------------------------------------------------------------------------------
22 -- Non-Lua syntax extensions
24 --------------------------------------------------------------------------------
26 local gg = require 'metalua.grammar.generator'
30 local _M = gg.future(M)
32 ---------------------------------------------------------------------------
33 -- Algebraic Datatypes
34 ----------------------------------------------------------------------------
35 local function adt (lx)
36 local node = _M.id (lx)
37 local tagval = node[1]
38 -- tagkey = `Pair{ `String "key", `String{ -{tagval} } }
39 local tagkey = { tag="Pair", {tag="String", "tag"}, {tag="String", tagval} }
40 if lx:peek().tag == "String" or lx:peek().tag == "Number" then
41 -- TODO support boolean litterals
42 return { tag="Table", tagkey, lx:next() }
43 elseif lx:is_keyword (lx:peek(), "{") then
44 local x = M.table.table (lx)
45 table.insert (x, 1, tagkey)
47 else return { tag="Table", tagkey } end
50 M.adt = gg.sequence{ "`", adt, builder = unpack }
52 M.expr.primary :add(M.adt)
54 ----------------------------------------------------------------------------
56 ----------------------------------------------------------------------------
57 M.lambda_expr = gg.sequence{
58 "|", _M.func_params_content, "|", _M.expr,
59 builder = function (x)
60 local li = x[2].lineinfo
61 return { tag="Function", x[1],
62 { {tag="Return", x[2], lineinfo=li }, lineinfo=li } }
65 M.expr.primary :add (M.lambda_expr)
67 --------------------------------------------------------------------------------
68 -- Allows to write "a `f` b" instead of "f(a, b)". Taken from Haskell.
69 --------------------------------------------------------------------------------
70 function M.expr_in_backquotes (lx) return M.expr(lx, 35) end -- 35=limited precedence
71 M.expr.infix :add{ name = "infix function",
72 "`", _M.expr_in_backquotes, "`", prec = 35, assoc="left",
73 builder = function(a, op, b) return {tag="Call", op[1], a, b} end }
75 --------------------------------------------------------------------------------
76 -- C-style op+assignments
77 -- TODO: no protection against side-effects in LHS vars.
78 --------------------------------------------------------------------------------
79 local function op_assign(kw, op)
80 local function rhs(a, b) return { tag="Op", op, a, b } end
82 if #a ~= #b then gg.parse_error "assymetric operator+assignment" end
84 local r = { tag="Set", a, right }
85 for i=1, #a do right[i] = { tag="Op", op, a[i], b[i] } end
92 local ops = { add='+='; sub='-='; mul='*='; div='/=' }
93 for ast_op_name, keyword in pairs(ops) do op_assign(keyword, ast_op_name) end