Fix parsing \verb command

See #828.
This commit is contained in:
Patrick Förster 2023-04-29 10:17:19 +02:00
parent b61313e3b0
commit 6188ddf4fb
7 changed files with 66 additions and 6 deletions

View file

@ -44,6 +44,11 @@ impl<'a> Parser<'a> {
self.builder.token(kind.into(), text);
}
fn eat_remap(&mut self, kind: SyntaxKind) {
let (_, text) = self.lexer.eat().unwrap();
self.builder.token(kind.into(), text);
}
fn peek(&self) -> Option<Token> {
self.lexer.peek()
}
@ -98,7 +103,7 @@ impl<'a> Parser<'a> {
self.eat();
self.builder.finish_node();
}
Token::Word | Token::Comma => self.text(context),
Token::Pipe | Token::Word | Token::Comma => self.text(context),
Token::Eq => self.eat(),
Token::Dollar => self.formula(),
Token::CommandName(name) => match name {
@ -141,6 +146,7 @@ impl<'a> Parser<'a> {
CommandName::EnvironmentDefinition => self.environment_definition(),
CommandName::BeginBlockComment => self.block_comment(),
CommandName::EndBlockComment => self.generic_command(),
CommandName::VerbatimBlock => self.verbatim_block(),
CommandName::GraphicsPath => self.graphics_path(),
},
}
@ -158,6 +164,7 @@ impl<'a> Parser<'a> {
| Token::Whitespace
| Token::LineComment
| Token::Word
| Token::Pipe
| Token::Comma
) && (context.allow_comma || kind != Token::Comma)
})
@ -219,7 +226,7 @@ impl<'a> Parser<'a> {
self.eat();
self.trivia();
match self.peek() {
Some(Token::Word) => {
Some(Token::Word | Token::Pipe) => {
self.key();
}
Some(Token::CommandName(_)) => {
@ -244,6 +251,7 @@ impl<'a> Parser<'a> {
| Token::Whitespace
| Token::LineComment
| Token::Word
| Token::Pipe
| Token::Comma
)
})
@ -298,7 +306,7 @@ impl<'a> Parser<'a> {
self.eat();
self.trivia();
match self.peek() {
Some(Token::Word) => {
Some(Token::Word | Token::Pipe) => {
self.key();
}
Some(_) | None => {}
@ -334,7 +342,12 @@ impl<'a> Parser<'a> {
self.eat();
while self
.peek()
.filter(|&kind| matches!(kind, Token::Whitespace | Token::LineComment | Token::Word))
.filter(|&kind| {
matches!(
kind,
Token::Whitespace | Token::LineComment | Token::Word | Token::Pipe
)
})
.is_some()
{
self.eat();
@ -390,7 +403,7 @@ impl<'a> Parser<'a> {
while let Some(kind) = self.peek() {
match kind {
Token::LineBreak | Token::Whitespace | Token::LineComment => self.eat(),
Token::Word => {
Token::Word | Token::Pipe => {
self.key_value_pair();
if self.peek() == Some(Token::Comma) {
self.eat();
@ -1116,6 +1129,23 @@ impl<'a> Parser<'a> {
self.builder.finish_node();
}
fn verbatim_block(&mut self) {
self.builder.start_node(GENERIC_COMMAND.into());
self.eat();
self.builder.finish_node();
self.trivia();
if self.peek() == Some(Token::Pipe) {
self.eat_remap(SyntaxKind::VERBATIM);
while let Some(kind) = self.peek() {
self.eat_remap(SyntaxKind::VERBATIM);
if kind == Token::Pipe {
break;
}
}
}
}
}
pub fn parse_latex(text: &str, config: &SyntaxConfig) -> GreenNode {

View file

@ -38,6 +38,7 @@ impl<'a> Lexer<'a> {
Token::RParen => SyntaxKind::R_PAREN,
Token::Comma => SyntaxKind::COMMA,
Token::Eq => SyntaxKind::EQUALITY_SIGN,
Token::Pipe => SyntaxKind::WORD,
Token::Word => SyntaxKind::WORD,
Token::Dollar => SyntaxKind::DOLLAR,
Token::CommandName(_) => SyntaxKind::COMMAND_NAME,

View file

@ -80,6 +80,7 @@ pub fn classify(name: &str, config: &SyntaxConfig) -> CommandName {
"graphicspath" => CommandName::GraphicsPath,
"iffalse" => CommandName::BeginBlockComment,
"fi" => CommandName::EndBlockComment,
"verb" => CommandName::VerbatimBlock,
_ if config.citation_commands.contains(name) => CommandName::Citation,
_ => CommandName::Generic,
}

View file

@ -35,7 +35,10 @@ pub enum Token {
#[token("=")]
Eq,
#[regex(r"[^\s\\%\{\},\$\[\]\(\)=]+")]
#[token("|")]
Pipe,
#[regex(r"[^\s\\%\{\},\$\[\]\(\)=\|]+")]
Word,
#[regex(r"\$\$?")]
@ -117,6 +120,7 @@ pub enum CommandName {
GraphicsPath,
BeginBlockComment,
EndBlockComment,
VerbatimBlock,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]

View file

@ -0,0 +1,22 @@
---
source: crates/parser/src/latex.rs
expression: root
input_file: crates/parser/src/test_data/latex/issue_828.txt
---
ROOT@0..51
PREAMBLE@0..51
GENERIC_COMMAND@0..5
COMMAND_NAME@0..5 "\\verb"
VERBATIM@5..6 "|"
VERBATIM@6..17 "<STATEMENT>"
VERBATIM@17..22 " "
VERBATIM@22..24 "if"
VERBATIM@24..25 "("
VERBATIM@25..31 "<expr>"
VERBATIM@31..32 ")"
VERBATIM@32..33 "{"
VERBATIM@33..43 "<body>else"
VERBATIM@43..44 "{"
VERBATIM@44..50 "<body>"
VERBATIM@50..51 "|"

View file

@ -0,0 +1 @@
\verb|<STATEMENT> if(<expr>){<body>else{<body>|