-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser_spec.lua
More file actions
172 lines (150 loc) · 5.4 KB
/
Copy pathparser_spec.lua
File metadata and controls
172 lines (150 loc) · 5.4 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
-- Unit tests for the parser. Expected trees follow the AST format of the
-- parser bundled with moonscript exactly, including [-1] position
-- annotations. The suite in tree_spec.lua covers whole .moon files against
-- expected outputs; these are quick hand-checked cases with the trees
-- written out inline.
describe("moonscript_parser", function()
local parse
setup(function()
-- TEST_SLOW=1 runs the suite against the pure Lua parser
if os.getenv("TEST_SLOW") then
package.preload["moonscript_parser.native"] = function()
return dofile("moonscript_parser/slow.lua")
end
end
parse = require "moonscript_parser"
end)
it("parses assignment", function()
assert.same({
{"assign",
{{"ref", "x", [-1] = 1}},
{{"number", "5", [-1] = 4}},
[-1] = 1},
}, parse.string("x = 5"))
end)
it("parses an open call", function()
assert.same({
{"chain",
{"ref", "print", [-1] = 1},
{"call", {{"ref", "x", [-1] = 6}}},
[-1] = 1},
}, parse.string("print x"))
end)
it("parses table with self-assign and string key", function()
assert.same({
{"assign",
{{"ref", "t", [-1] = 1}},
{{"table", {
{{"key_literal", "name"}, {"ref", "name", [-1] = 11}},
{{"string", '"', "k"}, {"ref", "v", [-1] = 17}},
}, [-1] = 4}},
[-1] = 1},
}, parse.string([[t = {:name, "k": v}]]))
end)
it("parses a function literal with binary op body", function()
assert.same({
{"assign",
{{"ref", "f", [-1] = 1}},
{{"fndef", {{"a"}}, {}, "slim", {
{"exp", {"ref", "a", [-1] = 11}, "+", {"number", "1", [-1] = 15}, [-1] = 11},
}, [-1] = 4}},
[-1] = 1},
}, parse.string("f = (a) -> a + 1"))
end)
it("parses an indented block", function()
assert.same({
{"if", {"ref", "x", [-1] = 3}, {
{"chain", {"ref", "y", [-1] = 8}, {"call", {}}, [-1] = 8},
}, [-1] = 1},
}, parse.string("if x\n y!"))
end)
it("parses lua strings, reconstructing the open delimiter", function()
assert.same({
{"assign",
{{"ref", "x", [-1] = 1}},
{{"string", "[==[", "str", [-1] = 4}},
[-1] = 1},
}, parse.string("x = [==[str]==]"))
end)
it("parses an anonymous class with a nil name slot", function()
local tree = assert(parse.string("x = class"))
local class_node = tree[1][3][1]
assert.same("class", class_node[1])
assert.is_nil(class_node[2])
assert.same("", class_node[3])
assert.same({}, class_node[4])
end)
it("parses an empty file", function()
assert.same({}, parse.string(""))
end)
it("parses a comment-only file", function()
assert.same({}, parse.string("-- nothing here"))
end)
it("fails on unbalanced parens", function()
local tree, err = parse.string("x = (a + b")
assert.is_nil(tree)
assert.is_string(err)
end)
it("fails on a bad outdent", function()
assert.is_nil((parse.string("if x\n y\n z")))
end)
it("rejects a non-assignable left hand side", function()
local tree, err = parse.string("f! = 5")
assert.is_nil(tree)
assert.matches("not assignable", err)
assert.matches("line 1", err)
end)
it("reports a line position for parse failures", function()
local tree, err = parse.string("x = 1\ny = 2\nz = (a +")
assert.is_nil(tree)
assert.matches("line 3", err)
tree, err = parse.string('x = "hello\ny = 1')
assert.is_nil(tree)
assert.matches("line 2", err)
tree, err = parse.string("import a from")
assert.is_nil(tree)
assert.matches("line 1", err)
end)
-- regression: T() labels were tried in this grammar and removed. Value
-- tries Comprehension before String, so at "[[" the parser attempts to
-- parse string content as code; a label reached during such an attempt
-- rejected valid programs like these.
it("parses code-like content inside long strings", function()
assert.is_table(parse.string("y = [[if x then import a]] .. z"))
assert.is_table(parse.string("x = [[=[hi]] .. 1"))
assert.is_table(parse.string([=[x = y .. [[Flow:extend("]] .. z .. [[")]] .. w]=]))
end)
it("keeps the parser reusable after a failed parse", function()
assert.is_nil((parse.string("x = (")))
assert.same({
{"assign",
{{"ref", "x", [-1] = 1}},
{{"number", "1", [-1] = 4}},
[-1] = 1},
}, parse.string("x = 1"))
end)
it("returns nil, err instead of raising on the recursion depth limit", function()
local tree, err = parse.string(("("):rep(6000))
assert.is_nil(tree)
assert.matches("max recursion depth", err)
end)
it("disables do expressions inside loop headers", function()
-- `do` after the while condition is the block keyword, not a do-expression
local tree = assert(parse.string("while x do print 1"))
assert.same("while", tree[1][1])
-- but a do-expression is fine in normal expression position
local tree2 = assert(parse.string("x = do\n 5"))
assert.same("do", tree2[1][3][1][1])
end)
it("handles interpolation containing a lua string", function()
local tree = assert(parse.string([=[x = "a#{ [[long]] }b"]=]))
local str = tree[1][3][1]
assert.same("string", str[1])
assert.same("a", str[3])
assert.same("interpolate", str[4][1])
assert.same("string", str[4][2][1])
assert.same("[[", str[4][2][2])
assert.same("long", str[4][2][3])
assert.same("b", str[5])
end)
end)