This repository was archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 107
/
Copy pathsnippet-body.pegjs
82 lines (73 loc) · 2.99 KB
/
snippet-body.pegjs
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
{
// Joins all consecutive strings in a collection without clobbering any
// non-string members.
function coalesce (parts) {
const result = [];
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const ri = result.length - 1;
if (typeof part === 'string' && typeof result[ri] === 'string') {
result[ri] = result[ri] + part;
} else {
result.push(part);
}
}
return result;
}
function flatten (parts) {
return parts.reduce(function (flat, rest) {
return flat.concat(Array.isArray(rest) ? flatten(rest) : rest);
}, []);
}
}
bodyContent = content:(tabStop / bodyContentText)* { return content; }
bodyContentText = text:bodyContentChar+ { return text.join(''); }
bodyContentChar = escaped / !tabStop char:. { return char; }
escaped = '\\' char:. { return char; }
tabStop = tabStopWithTransformation / tabStopWithPlaceholder / tabStopWithoutPlaceholder / simpleTabStop
simpleTabStop = '$' index:[0-9]+ {
return { index: parseInt(index.join("")), content: [] };
}
tabStopWithoutPlaceholder = '${' index:[0-9]+ '}' {
return { index: parseInt(index.join("")), content: [] };
}
tabStopWithPlaceholder = '${' index:[0-9]+ ':' content:placeholderContent '}' {
return { index: parseInt(index.join("")), content: content };
}
tabStopWithTransformation = '${' index:[0-9]+ substitution:transformationSubstitution '}' {
return {
index: parseInt(index.join(""), 10),
content: [],
substitution: substitution
};
}
placeholderContent = content:(tabStop / placeholderContentText / variable )* { return flatten(content); }
placeholderContentText = text:placeholderContentChar+ { return coalesce(text); }
placeholderContentChar = escaped / placeholderVariableReference / !tabStop !variable char:[^}] { return char; }
placeholderVariableReference = '$' digit:[0-9]+ {
return { index: parseInt(digit.join(""), 10), content: [] };
}
variable = '${' variableContent '}' {
return ''; // we eat variables and do nothing with them for now
}
variableContent = content:(variable / variableContentText)* { return content; }
variableContentText = text:variableContentChar+ { return text.join(''); }
variableContentChar = !variable char:('\\}' / [^}]) { return char; }
escapedForwardSlash = pair:'\\/' { return pair; }
// A pattern and replacement for a transformed tab stop.
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[imy]* {
let reFind = new RegExp(find.join(''), flags.join('') + 'g');
return { find: reFind, replace: replace[0] };
}
formatString = content:(formatStringEscape / formatStringReference / escapedForwardSlash / [^/])+ {
return content;
}
// Backreferencing a substitution. Different from a tab stop.
formatStringReference = '$' digits:[0-9]+ {
return { backreference: parseInt(digits.join(''), 10) };
};
// One of the special control flags in a format string for case folding and
// other tasks.
formatStringEscape = '\\' flag:[ULulErn$] {
return { escape: flag };
}