Skip to content

Commit b3a98c9

Browse files
Parse many literals along side idents in names (#398)
* Parse many literals along side idents in names * Accept ints as literals We will not accept floats because `123.123` is a float literal, but `123 .123` is a int literal followed by a class called `123`. This could be confusing so it will not be accepted. Ints can have leading zeros, like `0123`, but this is not guarranteed by the rust compiler to always work, which could cause future errors. An example would be truncating `001` to `1`. * Limit accepted literals using existing function * Update error output for non-string-literal * Test output of ints with specified type This outputs exactly what is written, which is the obvious behaviour * Use nightly version to generate output Previous verison was not using nightly, causing errors in the automated test that are using nightly * Replace "byte_string" with "raw_string" in test --------- Co-authored-by: Chris Wong <lambda.fairy@gmail.com>
1 parent 0de60b0 commit b3a98c9

File tree

3 files changed

+41
-34
lines changed

3 files changed

+41
-34
lines changed

maud/tests/basic_syntax.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,19 @@ fn raw_string_literals_in_attribute_names() {
201201

202202
#[test]
203203
fn other_literals_in_attribute_names() {
204-
let result =
205-
html! { this b"byte_string"="false" 123="123" 2.5 true 'a'="a" b'b'="b" of-course {} };
204+
let result = html! { this r#"raw_string"#="false" 123="123" 123usize "2.5" true of-course {} };
206205
assert_eq!(
207206
result.into_string(),
208-
r#"<this byte_string="false" 123="123" 2.5 true a="a" b="b" of-course></this>"#
207+
r#"<this raw_string="false" 123="123" 123usize 2.5 true of-course></this>"#
208+
);
209+
}
210+
211+
#[test]
212+
fn idents_and_literals_in_names() {
213+
let result = html! { custom:element-001 test:123-"test"="123" .m-2.p-2 {} };
214+
assert_eq!(
215+
result.into_string(),
216+
r#"<custom:element-001 class="m-2 p-2" test:123-test="123"></custom:element-001>"#
209217
);
210218
}
211219

maud/tests/warnings/non-string-literal.stderr

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,29 @@
1-
error: literal must be double-quoted: `"42"`
2-
--> $DIR/non-string-literal.rs:5:9
3-
|
4-
5 | 42
5-
| ^^
6-
7-
error: literal must be double-quoted: `"42usize"`
8-
--> $DIR/non-string-literal.rs:6:9
9-
|
10-
6 | 42usize
11-
| ^^^^^^^
12-
131
error: literal must be double-quoted: `"42.0"`
14-
--> $DIR/non-string-literal.rs:7:9
2+
--> tests/warnings/non-string-literal.rs:7:9
153
|
164
7 | 42.0
175
| ^^^^
186

197
error: literal must be double-quoted: `"a"`
20-
--> $DIR/non-string-literal.rs:8:9
8+
--> tests/warnings/non-string-literal.rs:8:9
219
|
2210
8 | 'a'
2311
| ^^^
2412

2513
error: expected string
26-
--> $DIR/non-string-literal.rs:9:9
14+
--> tests/warnings/non-string-literal.rs:9:9
2715
|
2816
9 | b"a"
2917
| ^^^^
3018

3119
error: expected string
32-
--> $DIR/non-string-literal.rs:10:9
20+
--> tests/warnings/non-string-literal.rs:10:9
3321
|
3422
10 | b'a'
3523
| ^^^^
3624

3725
error: attribute value must be a string
38-
--> $DIR/non-string-literal.rs:13:24
26+
--> tests/warnings/non-string-literal.rs:13:24
3927
|
4028
13 | input disabled=true;
4129
| ^^^^
@@ -44,7 +32,7 @@ error: attribute value must be a string
4432
= help: to toggle the attribute, use square brackets: `disabled[some_boolean_flag]`
4533

4634
error: attribute value must be a string
47-
--> $DIR/non-string-literal.rs:14:24
35+
--> tests/warnings/non-string-literal.rs:14:24
4836
|
4937
14 | input disabled=false;
5038
| ^^^^^

maud_macros/src/parse.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,13 @@ impl Parser {
204204
}
205205
// Boolean literals are idents, so `Lit::Bool` is handled in
206206
// `markup`, not here.
207-
Lit::Int(..) | Lit::Float(..) => {
207+
Lit::Int(lit_int) => {
208+
return ast::Markup::Literal {
209+
content: lit_int.to_string(),
210+
span: SpanRange::single_span(literal.span()),
211+
};
212+
}
213+
Lit::Float(..) => {
208214
emit_error!(literal, r#"literal must be double-quoted: `"{}"`"#, literal);
209215
}
210216
Lit::Char(lit_char) => {
@@ -702,27 +708,32 @@ impl Parser {
702708
/// Parses an identifier, without dealing with namespaces.
703709
fn try_name(&mut self) -> Option<TokenStream> {
704710
let mut result = Vec::new();
705-
match self.peek() {
706-
Some(token @ TokenTree::Ident(_)) | Some(token @ TokenTree::Literal(_)) => {
707-
self.advance();
708-
result.push(token);
709-
}
710-
_ => return None,
711-
};
712-
let mut expect_ident = false;
711+
let mut expect_ident_or_literal = true;
713712
loop {
714-
expect_ident = match self.peek() {
713+
expect_ident_or_literal = match self.peek() {
715714
Some(TokenTree::Punct(ref punct)) if punct.as_char() == '-' => {
716715
self.advance();
717716
result.push(TokenTree::Punct(punct.clone()));
718717
true
719718
}
720-
Some(TokenTree::Ident(ref ident)) if expect_ident => {
719+
Some(token @ TokenTree::Ident(_)) if expect_ident_or_literal => {
721720
self.advance();
722-
result.push(TokenTree::Ident(ident.clone()));
721+
result.push(token);
723722
false
724723
}
725-
_ => break,
724+
Some(TokenTree::Literal(ref literal)) if expect_ident_or_literal => {
725+
self.literal(literal.clone());
726+
self.advance();
727+
result.push(TokenTree::Literal(literal.clone()));
728+
false
729+
}
730+
_ => {
731+
if result.is_empty() {
732+
return None;
733+
} else {
734+
break;
735+
}
736+
}
726737
};
727738
}
728739
Some(result.into_iter().collect())

0 commit comments

Comments
 (0)