aboutsummaryrefslogtreecommitdiffstats
path: root/alv/parsing.moon
blob: d9bc5acdedcb3d0597598af95636cc476a60fd3f (plain)
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
79
80
81
82
83
84
85
86
87
88
----
-- Lpeg Grammar for parsing `alive` code.
--
-- @module parsing
import Cell, RootCell, ArrayCell, StructCell, Constant, TemplateString, Tag from require 'alv.ast'
import R, S, P, V, C, Ct from require 'lpeg'

-- whitespace
wc = S ' \t\r\n'
cexpr = (P '(') * ((V 'cexpr') + (1 - P ')'))^0 * (P ')')
ccell = P {
  (P '#') * (V 'cexpr')
  :cexpr
}
cline = (P '##') * (1 - (P '\n'))^0
comment = cline + ccell
mspace = (comment + wc)^0 / 1            -- optional whitespace
space  = (wc^1 * (comment^0 * wc)^0) / 1 -- required whitespace

-- atoms
digit = R '09'
first = (R 'az', 'AZ') + S '-_+*^%/.=~!?$><'
sym = first * (first + digit)^0 / Constant\parse 'sym'

strd = '"' * (C ((P '\\"') + (P '\\\\') + (1 - P '"'))^0) * '"' / Constant\parse 'str', '\"'
strq = "'" * (C ((P "\\'") + (P '\\\\') + (1 - P "'"))^0) * "'" / Constant\parse 'str', '\''
str = strd + strq

int = digit^1
fract = digit^1 * '/' * digit^1
float = (digit^1 * '.' * digit^0) + (digit^0 * '.' * digit^1)
num = ((P '-')^-1 * (float + fract + int)) / Constant\parse 'num'

tag = (P '[') * (digit^1 / Tag.parse) * (P ']')

tpltext = ((P '\\"') + (P '\\\\') + (P '\\$') + (1 - (P '"') - (P '$')))^1 / 1
tplcont = Ct (('$' * (V 'expr')) + tpltext)^0
tplstr = (P '$') * tag^-1 * sym * '"' * tplcont * '"' / TemplateString\parse

expitem = tplstr + (V 'expr')
explist = Ct mspace * (expitem * (space * expitem)^0 * mspace)^-1

cell = (P '(') * tag^-1 * explist * (P ')') / Cell.parse
array = (P '[') * explist * (P ']') / ArrayCell\parse
struct = (P '{') * explist * (P '}') / StructCell\parse

atom = num + sym + str
expr = cell + array + struct + atom

root = P {
  explist / RootCell\parse
  :expr
}

cell = P {
  cell
  :expr
}

tplstr = P {
  tplstr
  :expr
}

program = root * -1

--- exports
-- @table exports
-- @tfield pattern comment
-- @tfield pattern space
-- @tfield pattern atom
-- @tfield pattern expr
-- @tfield pattern explist
-- @tfield pattern explist
-- @tfield pattern cell
-- @tfield pattern root
-- @tfield pattern program the main parsing entrypoint
{
  :comment
  :space
  :atom
  :expr
  :explist
  :tplstr
  :cell
  :root
  :program
}