blob: 841e61bdb7b6e06578d530ba499775e969fc1859 (
plain)
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
|
use crate::token::*;
pub use rules::*;
peg::parser! {
pub grammar rules() for str {
pub rule token_stream() -> TokenStream<'input>
= _ tokens:(token() ** _) _ { TokenStream(tokens) }
pub rule token() -> Token<'input>
= number:number() { Token::Number(number) }
/ string:string() { Token::String(string) }
/ ident:ident() { Token::Ident(ident) }
/ punct:punct() { Token::Punct(punct) }
rule ident() -> &'input str
= $(
['a'..='z' | 'A' ..='Z' | '_' ]
['a'..='z' | 'A' ..='Z' | '_' | '0'..='9']*
)
rule punct() -> Punct
= ch:punct_char() spacing:spacing() { Punct(ch, spacing) }
rule punct_char() -> char
= !number() !string() !ident() !__ ch:[_] { ch }
rule spacing() -> Spacing
= &punct_char() { Spacing::Joint }
/ { Spacing::Alone }
rule number() -> &'input str
= $(['0'..='9'] ['0'..='9' | 'a'..='z' | 'A'..='Z' | '_']*)
rule string() -> String<'input>
= "\"" pieces:string_piece()* "\"" {
String {
pieces,
kind: StringKind::String,
}
}
/ "r\"" chars:$([^'"']*) "\"" {
String {
pieces: vec![StringPiece::Chars(chars)],
kind: StringKind::RawString,
}
}
/ "```" newline() pieces:script_string_piece()* "```" {
String {
pieces,
kind: StringKind::ScriptString,
}
}
rule string_piece() -> StringPiece<'input>
= chars:$((!"{{" [^'"' | '\\'])+) { StringPiece::Chars(chars) }
/ "\\" escape:string_escape() { StringPiece::Escape(escape) }
/ string_interp()
rule string_escape() -> char
= "n" { '\n' }
/ "r" { '\r' }
/ "t" { '\t' }
/ "\\" { '\\' }
/ "\"" { '"' }
/ "0" { '\0' }
/ "x" digits:$(['0'..='7'] hex_digit()) {
u8::from_str_radix(digits, 16).unwrap().into()
}
/ "u{" digits:$(hex_digit()*<1,6>) "}" { ?
u32::from_str_radix(digits, 16).unwrap().try_into().or(Err("Invalid unicode escape"))
}
rule script_string_piece() -> StringPiece<'input>
= chars:$((!"{{" !"```" [_])+) { StringPiece::Chars(chars) }
/ string_interp()
rule string_interp() -> StringPiece<'input>
= "{{" _ tokens:(subtoken() ++ _) _ "}}" {
StringPiece::Interp(TokenStream(tokens))
}
rule subtoken() -> Token<'input>
= !"}}" token:token() { token }
rule hex_digit()
= ['0'..='9' | 'a'..='f' | 'A'..='F']
/// Mandatory whitespace
rule __
= ([' ' | '\t'] / quiet!{newline()} / quiet!{comment()})+
/// Optional whitespace
rule _
= quiet!{__?}
rule comment()
= "//" (!newline() [_])* (newline() / ![_])
/ "/*" (!"*/" [_])* "*/"
rule newline()
= ['\n' | '\r']
}
}
|