forked from stevenxxiu/tree-sitter-mail
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrammar.js
78 lines (67 loc) · 2.85 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
/**
* @file Email parser
* @author Steven Xu <[email protected]>
* @author Daniel Fichtinger <[email protected]>
* @license MIT
*/
/// <reference types="tree-sitter-cli/dsl" />
// @ts-check
const SPECIAL = /[()<>@,;:\\".\[\]]/
const CTL = /[\x00-\x1f\x7f]/
const NEWLINE = /\r?\n/
const EMAIL = /(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
export default grammar({
name: 'mail',
extras: (_$) => [' '],
rules: {
source_file: ($) => seq($._headers, optional(seq($.body_separator, $.body))),
_headers: ($) => repeat1(seq($._header, NEWLINE)),
_header: ($) => choice(prec(1, $.header_email), prec(1, $.header_subject), $.header_other),
header_email: ($) =>
seq($.header_field_email,
$.header_separator,
choice(
seq(token(' '), choice(seq($.atom_block, $.email), $.email, $.atom_block, $.email_address)),
optional(token(' ')),
)),
header_other: ($) => seq($.header_field, $.header_separator, choice(optional(token(' ')), seq(token(' '), $.header_unstructured))),
header_subject: ($) => seq($.header_field_subject, $.header_separator, token(' '), $.subject),
header_separator: (_$) => ':',
header_field: (_$) => new RegExp(`[^${CTL.source.slice(1, -1)}\\s:]+`),
header_field_email: (_$) => choice('From', 'To', 'Cc', 'Bcc', 'Reply-To'),
header_field_subject: (_$) => 'Subject',
header_unstructured: (_$) => /.*/,
subject: (_$) => /.*/,
atom_block: ($) => repeat1(choice($.atom, $.quoted_string)),
atom: (_$) => new RegExp(`[^${SPECIAL.source.slice(1, -1)}\\s${CTL.source.slice(1, -1)}]+`),
quoted_string: (_$) => /"[^"\\\n]+"/,
email_delimiter: (_$) => choice(token('>'), token('<')),
email_address: (_$) => EMAIL,
email: ($) => seq(
$.email_delimiter,
$.email_address,
$.email_delimiter,
),
body_separator: (_$) => NEWLINE,
body: ($) => repeat1(choice(
prec(3, $._empty_line),
prec(2, $.quote_group),
prec(1, $.body_block),
)),
quote_group: ($) => prec.right(repeat1($._quoted_line)),
quoted_block: ($) => seq(
$.quote_marker,
$.quote_contents
),
_quoted_line: ($) =>
seq(
$.quoted_block,
NEWLINE,
),
quote_marker: (_$) => token('>'),
quote_contents: (_$) => token(/[^\r\n]*/),
body_block: ($) => prec.right(repeat1($._body_line)),
_body_line: (_$) => seq(/[^\r\n>].*/, NEWLINE),
_empty_line: (_$) => NEWLINE,
},
})