-
Notifications
You must be signed in to change notification settings - Fork 11
/
grammar.js
117 lines (98 loc) · 2.73 KB
/
grammar.js
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
const NEWLINE = /\r?\n/;
const WHITE_SPACE = /[\t\f\v ]+/;
const ANYTHING = /[^\r\n]+/;
module.exports = grammar({
name: "diff",
extras: ($) => [WHITE_SPACE],
rules: {
source: ($) =>
seq(
repeat(choice($.block, seq(optional($._line), NEWLINE))),
optional($._line)
),
_line: ($) =>
choice(
$.file_change,
$.binary_change,
$.index,
$.similarity,
$.old_file,
$.new_file,
$.location,
$.addition,
$.deletion,
$.context,
$.comment
),
block: ($) =>
prec.right(
seq(
$.command,
NEWLINE,
repeat(
seq(
choice($.file_change, $.binary_change, $.index, $.similarity),
NEWLINE
)
),
optional(seq($.old_file, NEWLINE, $.new_file, NEWLINE, $.hunks))
)
),
hunks: ($) => prec.right(repeat1($.hunk)),
hunk: ($) =>
prec.right(
seq(
field("location", $.location),
NEWLINE,
optional(field("changes", $.changes))
)
),
changes: ($) =>
prec.right(
repeat1(
seq(
choice($.addition, $.deletion, $.context),
prec.right(repeat1(NEWLINE))
)
)
),
command: ($) => iseq("diff", alias(/[-\w]+/, $.argument), $.filename),
file_change: ($) =>
choice(
seq(choice("new", "deleted"), "file", "mode", $.mode),
seq(choice("new", "old"), "mode", $.mode),
seq("rename", choice("from", "to"), $.filename)
),
binary_change: ($) =>
iseq("Binary", "files", $.filename, "and", $.filename, "differ"),
index: ($) => iseq("index", $.commit, "..", $.commit, optional($.mode)),
similarity: ($) => iseq("similarity", "index", alias(/\d+/, $.score), "%"),
old_file: ($) => iseq("---", $.filename),
new_file: ($) => iseq("+++", $.filename),
location: ($) =>
iseq("@@", $.linerange, $.linerange, "@@", optional(ANYTHING)),
addition: ($) =>
choice(
iseq("+", optional(ANYTHING)),
iseq("++", optional(ANYTHING)),
iseq("+++"),
iseq("++++", optional(ANYTHING))
),
deletion: ($) =>
choice(
iseq("-", optional(ANYTHING)),
iseq("--", optional(ANYTHING)),
iseq("---"),
iseq("----", optional(ANYTHING))
),
context: ($) => token(prec(-1, ANYTHING)),
comment: ($) => iseq("#", optional(ANYTHING)),
linerange: ($) => /[-\+]\d+(,\d+)?/,
filename: ($) => repeat1(/\S+/),
commit: ($) => /[a-f0-9]{7,40}/,
mode: ($) => /\d+/,
},
});
function iseq(start_token, ...tokens) {
return seq(token.immediate(start_token), ...tokens);
}