scansion/parser.lua

Sat, 29 Dec 2018 02:52:55 -0500

author
Waqas Hussain <waqas20@gmail.com>
date
Sat, 29 Dec 2018 02:52:55 -0500
changeset 163
0e2150680a25
parent 162
f888f236321f
permissions
-rw-r--r--

parser: Prefix parse errors with "ParserError: "

0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local function parse(data)
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 local parsed = {
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 objects = {};
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 actions = {};
147
db39e8e9146c scansion.parser: Ensure script objects always have tags, even if empty
Matthew Wild <mwild1@gmail.com>
parents: 79
diff changeset
5 tags = {};
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 };
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 local line_number = 0;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local last_object;
43
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
10 local annotation;
72
4fde8d4a4c76 scansion.parser: Whitespace fix
Matthew Wild <mwild1@gmail.com>
parents: 70
diff changeset
11
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
12 local function parse_error(text)
163
0e2150680a25 parser: Prefix parse errors with "ParserError: "
Waqas Hussain <waqas20@gmail.com>
parents: 162
diff changeset
13 return nil, "ParseError: " .. text .. " (line " .. line_number .. ")";
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
14 end
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
15
42
67d50889b7fe scansion.parser: Don't skip blank lines (otherwise line numbers get skewed)
Matthew Wild <mwild1@gmail.com>
parents: 19
diff changeset
16 for line in data:gmatch("([^\r\n]*)\r?\n") do
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 line_number = line_number + 1;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 if line:sub(1,1) == "[" then
79
63d573be3f91 scansion.parser: Remove unused variable (thanks luacheck)
Matthew Wild <mwild1@gmail.com>
parents: 78
diff changeset
19 local obj_type, name = line:match("^%[(%a+)%] (.+)$");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 if parsed.objects[name] then
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
22 return parse_error("Duplicate definition of '"..name.."'");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 parsed.objects[name] = {
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 type = obj_type:lower();
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 name = name;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 defined_line = line_number;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 };
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 last_object = parsed.objects[name];
47
1cbc0d9d132d scansion.parser: Allow property names to contain underscore
Kim Alvefur <zash@zash.se>
parents: 44
diff changeset
30 elseif line:match("^%s+[%a_]+:.+$") then
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 if not last_object then
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
32 return parse_error("Unexpected outside of an object definition");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 end
47
1cbc0d9d132d scansion.parser: Allow property names to contain underscore
Kim Alvefur <zash@zash.se>
parents: 44
diff changeset
34 local k, v = line:match("^%s+([%a_]+):%s*(.+)$")
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 last_object[k] = v;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 elseif #parsed.actions > 0 and line:sub(1,1) == "\t" then
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 table.insert(parsed.actions[#parsed.actions].extra, line:sub(2));
160
28aa762f11c7 Include line_start and line_end in action objects and action log events for /run end-point
Waqas Hussain <waqas20@gmail.com>
parents: 147
diff changeset
38 parsed.actions[#parsed.actions].line_end = line_number;
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 elseif line:match("^%s*$") or line:match("^#") or line:match("^([/-])%1") then
70
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
40 -- Blank line or comment
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
41 local in_header = (next(parsed.objects) == nil) and (next(parsed.actions) == nil);
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
42 if in_header and #line > 0 then
77
38066f635004 Ignore shebangs at the top of a script
Matthew Wild <mwild1@gmail.com>
parents: 72
diff changeset
43 if not parsed.title and not line:match("^#!") then
70
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
44 parsed.title = line:gsub("^[#-]+%s*", "");
78
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
45 elseif line:match("^##") then
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
46 local tag = line:gsub("^##%s*", "");
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
47 local k, v = tag:match("^([^:]+):%s*(.+)$");
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
48 if k then
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
49 -- Tag format: ## tagkey:tagvalue
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
50 parsed.tags[k] = v;
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
51 else
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
52 -- Tag format: ## tagfoobar
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
53 parsed.tags[tag] = true;
54bb54fe9ed2 main, scansion.parser: Allow scripts to include tags in comments at the beginning, which are included in JSON output
Matthew Wild <mwild1@gmail.com>
parents: 77
diff changeset
54 end
70
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
55 else
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
56 parsed.summary = (parsed.summary and parsed.summary.."\n" or "")..line:gsub("^[#-]+%s*", "");
43
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
57 end
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
58 else
70
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
59 -- Save as annotation for the following action
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
60 if #line == 0 then
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
61 if annotation then
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
62 annotation.closed = true;
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
63 end
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
64 elseif annotation or not line:match("^%-+$") then
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
65 if (not annotation) or annotation.closed then
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
66 annotation = { line };
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
67 else
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
68 table.insert(annotation, line);
2b62a714b5df scansion.parser: Read any comments at top of the file as script title (first line) and summary (following lines)
Matthew Wild <mwild1@gmail.com>
parents: 47
diff changeset
69 end
43
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
70 end
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
71 end
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 else
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 last_object = nil;
44
0dab1dc183c1 parser, objects.client: Experimental support for more liberal object names
Matthew Wild <mwild1@gmail.com>
parents: 43
diff changeset
74 local name, action, extra = line:match("^([^:]+) (%a+):?%s?(.*)$");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 if not name then
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
76 return parse_error("Unable to parse action");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 if not parsed.objects[name] then
162
f888f236321f Make current line number available in all error events
Waqas Hussain <waqas20@gmail.com>
parents: 160
diff changeset
79 return parse_error("The object '"..name.."' was not declared");
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 table.insert(parsed.actions, {
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 object_name = name;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 action = action:lower();
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 extra = {#extra>0 and extra or nil};
43
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
85 annotation = annotation and table.concat(annotation, "\n") or nil;
160
28aa762f11c7 Include line_start and line_end in action objects and action log events for /run end-point
Waqas Hussain <waqas20@gmail.com>
parents: 147
diff changeset
86 line_start = line_number;
28aa762f11c7 Include line_start and line_end in action objects and action log events for /run end-point
Waqas Hussain <waqas20@gmail.com>
parents: 147
diff changeset
87 line_end = line_number;
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 });
43
b37504fa3031 Add annotations to actions (by grabbing the preceding comment)
Matthew Wild <mwild1@gmail.com>
parents: 42
diff changeset
89 annotation = nil;
0
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 return parsed;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 end
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 return {
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 parse = parse;
2e31b584f8d9 It is better to write and run incomplete tests than not to run complete tests. -- Martin Fowler
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 };

mercurial