Skip to content
This repository has been archived by the owner on Jul 27, 2023. It is now read-only.

Commit

Permalink
Lex Jupyter line magic with Mode::Jupyter
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvmanila committed Jul 6, 2023
1 parent c174bbf commit 17bdc29
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 3 deletions.
5 changes: 4 additions & 1 deletion core/src/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub enum Mode {
Interactive,
/// The code consists of a single expression.
Expression,
/// The code is a Jupyter notebook.
Jupyter,
}

impl std::str::FromStr for Mode {
Expand All @@ -17,6 +19,7 @@ impl std::str::FromStr for Mode {
match s {
"exec" | "single" => Ok(Mode::Module),
"eval" => Ok(Mode::Expression),
"jupyter" => Ok(Mode::Jupyter),
_ => Err(ModeParseError),
}
}
Expand All @@ -28,6 +31,6 @@ pub struct ModeParseError;

impl std::fmt::Display for ModeParseError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, r#"mode must be "exec", "eval", or "single""#)
write!(f, r#"mode must be "exec", "eval", "jupyter", or "single""#)
}
}
34 changes: 32 additions & 2 deletions parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ pub struct Lexer<T: Iterator<Item = char>> {
pending: Vec<Spanned>,
// The current location.
location: TextSize,
// Lexer mode.
mode: Mode,
}

// generated in build.rs, in gen_phf()
Expand Down Expand Up @@ -213,7 +215,7 @@ pub fn lex_starts_at(
mode: Mode,
start_offset: TextSize,
) -> SoftKeywordTransformer<Lexer<std::str::Chars<'_>>> {
SoftKeywordTransformer::new(Lexer::new(source.chars(), start_offset), mode)
SoftKeywordTransformer::new(Lexer::new(source.chars(), mode, start_offset), mode)
}

impl<T> Lexer<T>
Expand All @@ -222,7 +224,7 @@ where
{
/// Create a new lexer from T and a starting location. You probably want to use
/// [`lex`] instead.
pub fn new(input: T, start: TextSize) -> Self {
pub fn new(input: T, mode: Mode, start: TextSize) -> Self {
let mut lxr = Lexer {
at_begin_of_line: true,
nesting: 0,
Expand All @@ -231,6 +233,7 @@ where
pending: Vec::with_capacity(5),
location: start,
window: CharWindow::new(input),
mode,
};
// Fill the window.
lxr.window.slide();
Expand Down Expand Up @@ -494,6 +497,28 @@ where
Ok(())
}

/// Lex a single magic command.
fn lex_magic_command(&mut self) -> LexResult {
let start_pos = self.get_pos();
let mut value = String::new();
loop {
match self.window[0] {
Some('\n' | '\r') | None => {
let end_pos = self.get_pos();
return Ok((Tok::MagicCommand(value), TextRange::new(start_pos, end_pos)));
}
Some(_) => {}
}
value.push(self.next_char().unwrap());
}
}

fn lex_and_emit_magic_command(&mut self) -> Result<(), LexicalError> {
let jupyter_magic = self.lex_magic_command()?;
self.emit(jupyter_magic);
Ok(())
}

/// Lex a string literal.
fn lex_string(&mut self, kind: StringKind) -> LexResult {
let start_pos = self.get_pos();
Expand Down Expand Up @@ -644,6 +669,11 @@ where
spaces = 0;
tabs = 0;
}
Some('%' | '!' | '?') if self.mode == Mode::Jupyter => {
self.lex_and_emit_magic_command()?;
spaces = 0;
tabs = 0;
}
Some('\x0C') => {
// Form feed character!
// Reset indentation for the Emacs user.
Expand Down
4 changes: 4 additions & 0 deletions parser/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub enum Tok {
/// the token stream prior to parsing.
#[cfg(feature = "full-lexer")]
NonLogicalNewline,
/// Jupyter magic commands which can start with `%`, `!` or `?`.
MagicCommand(String),
/// Token value for an indent.
Indent,
/// Token value for a dedent.
Expand Down Expand Up @@ -204,6 +206,7 @@ impl Tok {
Mode::Module => Tok::StartModule,
Mode::Interactive => Tok::StartInteractive,
Mode::Expression => Tok::StartExpression,
Mode::Jupyter => Tok::StartModule,
}
}
}
Expand All @@ -227,6 +230,7 @@ impl fmt::Display for Tok {
Newline => f.write_str("Newline"),
#[cfg(feature = "full-lexer")]
NonLogicalNewline => f.write_str("NonLogicalNewline"),
MagicCommand(value) => f.write_str(value),
Indent => f.write_str("Indent"),
Dedent => f.write_str("Dedent"),
StartModule => f.write_str("StartProgram"),
Expand Down

0 comments on commit 17bdc29

Please sign in to comment.