Ignore leading byte order mark in source files (#1021)
This commit is contained in:
parent
f3abb95c78
commit
8b49c0cbd1
@ -490,6 +490,7 @@ impl<'src> Lexer<'src> {
|
|||||||
'@' => self.lex_single(At),
|
'@' => self.lex_single(At),
|
||||||
'[' => self.lex_delimiter(BracketL),
|
'[' => self.lex_delimiter(BracketL),
|
||||||
'\n' | '\r' => self.lex_eol(),
|
'\n' | '\r' => self.lex_eol(),
|
||||||
|
'\u{feff}' => self.lex_single(ByteOrderMark),
|
||||||
']' => self.lex_delimiter(BracketR),
|
']' => self.lex_delimiter(BracketR),
|
||||||
'`' | '"' | '\'' => self.lex_string(),
|
'`' | '"' | '\'' => self.lex_string(),
|
||||||
'{' => self.lex_delimiter(BraceL),
|
'{' => self.lex_delimiter(BraceL),
|
||||||
@ -926,6 +927,7 @@ mod tests {
|
|||||||
BraceR => "}",
|
BraceR => "}",
|
||||||
BracketL => "[",
|
BracketL => "[",
|
||||||
BracketR => "]",
|
BracketR => "]",
|
||||||
|
ByteOrderMark => "\u{feff}",
|
||||||
Colon => ":",
|
Colon => ":",
|
||||||
ColonEquals => ":=",
|
ColonEquals => ":=",
|
||||||
Comma => ",",
|
Comma => ",",
|
||||||
|
@ -57,7 +57,12 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
/// `Parser::next`
|
/// `Parser::next`
|
||||||
fn unexpected_token(&self) -> CompileResult<'src, CompileError<'src>> {
|
fn unexpected_token(&self) -> CompileResult<'src, CompileError<'src>> {
|
||||||
self.error(CompileErrorKind::UnexpectedToken {
|
self.error(CompileErrorKind::UnexpectedToken {
|
||||||
expected: self.expected.iter().cloned().collect::<Vec<TokenKind>>(),
|
expected: self
|
||||||
|
.expected
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.filter(|kind| *kind != ByteOrderMark)
|
||||||
|
.collect::<Vec<TokenKind>>(),
|
||||||
found: self.next()?.kind,
|
found: self.next()?.kind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -302,6 +307,8 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
|
|
||||||
let mut eol_since_last_comment = false;
|
let mut eol_since_last_comment = false;
|
||||||
|
|
||||||
|
self.accept(ByteOrderMark)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let next = self.next()?;
|
let next = self.next()?;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ pub(crate) enum TokenKind {
|
|||||||
BraceR,
|
BraceR,
|
||||||
BracketL,
|
BracketL,
|
||||||
BracketR,
|
BracketR,
|
||||||
|
ByteOrderMark,
|
||||||
Colon,
|
Colon,
|
||||||
ColonEquals,
|
ColonEquals,
|
||||||
Comma,
|
Comma,
|
||||||
@ -51,6 +52,7 @@ impl Display for TokenKind {
|
|||||||
BraceR => "'}'",
|
BraceR => "'}'",
|
||||||
BracketL => "'['",
|
BracketL => "'['",
|
||||||
BracketR => "']'",
|
BracketR => "']'",
|
||||||
|
ByteOrderMark => "byte order mark",
|
||||||
Colon => "':'",
|
Colon => "':'",
|
||||||
ColonEquals => "':='",
|
ColonEquals => "':='",
|
||||||
Comma => "','",
|
Comma => "','",
|
||||||
@ -61,6 +63,7 @@ impl Display for TokenKind {
|
|||||||
Eol => "end of line",
|
Eol => "end of line",
|
||||||
Equals => "'='",
|
Equals => "'='",
|
||||||
EqualsEquals => "'=='",
|
EqualsEquals => "'=='",
|
||||||
|
EqualsTilde => "'=~'",
|
||||||
Identifier => "identifier",
|
Identifier => "identifier",
|
||||||
Indent => "indent",
|
Indent => "indent",
|
||||||
InterpolationEnd => "'}}'",
|
InterpolationEnd => "'}}'",
|
||||||
@ -70,7 +73,6 @@ impl Display for TokenKind {
|
|||||||
Plus => "'+'",
|
Plus => "'+'",
|
||||||
StringToken => "string",
|
StringToken => "string",
|
||||||
Text => "command text",
|
Text => "command text",
|
||||||
EqualsTilde => "'=~'",
|
|
||||||
Unspecified => "unspecified",
|
Unspecified => "unspecified",
|
||||||
Whitespace => "whitespace",
|
Whitespace => "whitespace",
|
||||||
}
|
}
|
||||||
|
52
tests/byte_order_mark.rs
Normal file
52
tests/byte_order_mark.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use crate::common::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignore_leading_byte_order_mark() {
|
||||||
|
Test::new()
|
||||||
|
.justfile(
|
||||||
|
"
|
||||||
|
\u{feff}foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.stderr("echo bar\n")
|
||||||
|
.stdout("bar\n")
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn non_leading_byte_order_mark_produces_error() {
|
||||||
|
Test::new()
|
||||||
|
.justfile(
|
||||||
|
"
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
\u{feff}
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.stderr(
|
||||||
|
"
|
||||||
|
error: Expected \'@\', comment, end of file, end of line, or identifier, but found byte order mark
|
||||||
|
|
|
||||||
|
3 | \u{feff}
|
||||||
|
| ^
|
||||||
|
")
|
||||||
|
.status(EXIT_FAILURE)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dont_mention_byte_order_mark_in_errors() {
|
||||||
|
Test::new()
|
||||||
|
.justfile("{")
|
||||||
|
.stderr(
|
||||||
|
"
|
||||||
|
error: Expected '@', comment, end of file, end of line, or identifier, but found '{'
|
||||||
|
|
|
||||||
|
1 | {
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.status(EXIT_FAILURE)
|
||||||
|
.run();
|
||||||
|
}
|
@ -3,6 +3,7 @@ mod test;
|
|||||||
|
|
||||||
mod assert_stdout;
|
mod assert_stdout;
|
||||||
mod assert_success;
|
mod assert_success;
|
||||||
|
mod byte_order_mark;
|
||||||
mod changelog;
|
mod changelog;
|
||||||
mod choose;
|
mod choose;
|
||||||
mod command;
|
mod command;
|
||||||
|
Loading…
Reference in New Issue
Block a user