Skip to content

Commit

Permalink
Parse all types of CaseContinuation in a case item
Browse files Browse the repository at this point in the history
Previously, the parser only recognized the `;;` terminator for a case
item. This commit changes the parser to recognize all types of
CaseContinuation, including `;&` and `;;&`.
  • Loading branch information
magicant committed Nov 11, 2024
1 parent 144261c commit 94f8ac1
Showing 1 changed file with 24 additions and 4 deletions.
28 changes: 24 additions & 4 deletions yash-syntax/src/parser/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ use super::core::Result;
use super::error::Error;
use super::error::SyntaxError;
use super::lex::Keyword::{Case, Esac, In};
use super::lex::Operator::{Bar, CloseParen, Newline, OpenParen, SemicolonSemicolon};
use super::lex::Operator::{Bar, CloseParen, Newline, OpenParen};
use super::lex::TokenId::{self, EndOfInput, Operator, Token};
use crate::syntax::CaseContinuation;
use crate::syntax::CaseItem;
use crate::syntax::CompoundCommand;

Expand Down Expand Up @@ -102,9 +101,13 @@ impl Parser<'_, '_> {
}

let body = self.maybe_compound_list_boxed().await?;
let continuation = CaseContinuation::default();

let continued = self.peek_token().await?.id == Operator(SemicolonSemicolon);
let continuation = match self.peek_token().await?.id {
Operator(op) => op.try_into().ok(),
_ => None,
};
let continued = continuation.is_some();
let continuation = continuation.unwrap_or_default();
if continued {
self.take_token_raw().await?;
}
Expand Down Expand Up @@ -190,6 +193,7 @@ mod tests {
use crate::alias::{AliasSet, EmptyGlossary, HashEntry};
use crate::source::Location;
use crate::source::Source;
use crate::syntax::CaseContinuation;
use assert_matches::assert_matches;
use futures_util::FutureExt;

Expand Down Expand Up @@ -321,6 +325,22 @@ mod tests {
assert_eq!(next.id, EndOfInput);
}

#[test]
fn parser_case_item_with_semicolon_and() {
let mut lexer = Lexer::from_memory("foo);&", Source::Unknown);
let mut parser = Parser::new(&mut lexer, &EmptyGlossary);

let (item, continued) = parser.case_item().now_or_never().unwrap().unwrap().unwrap();
assert_eq!(item.patterns.len(), 1);
assert_eq!(item.patterns[0].to_string(), "foo");
assert_eq!(item.body.0, []);
assert_eq!(item.continuation, CaseContinuation::FallThrough);
assert!(continued);

let next = parser.peek_token().now_or_never().unwrap().unwrap();
assert_eq!(next.id, EndOfInput);
}

#[test]
fn parser_case_item_missing_pattern_without_open_paren() {
let mut lexer = Lexer::from_memory(")", Source::Unknown);
Expand Down

0 comments on commit 94f8ac1

Please sign in to comment.