-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Interactive parser development example writing.
- Loading branch information
Showing
8 changed files
with
271 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "pie" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
pie_graph = "0.0.1" | ||
|
||
[dev-dependencies] | ||
dev_shared = { path = "../dev_shared" } | ||
assert_matches = "1" | ||
pest = "2" | ||
pest_meta = "2" | ||
pest_vm = "2" | ||
clap = { version = "4", features = ["derive"] } | ||
ratatui = "0.24" | ||
tui-textarea = "0.4" | ||
crossterm = "0.27" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use std::fmt::Write; | ||
use std::path::PathBuf; | ||
|
||
use clap::Parser; | ||
|
||
use pie::Pie; | ||
use pie::tracker::writing::WritingTracker; | ||
|
||
use crate::task::{Outputs, Tasks}; | ||
|
||
pub mod parse; | ||
pub mod task; | ||
pub mod editor; | ||
|
||
#[derive(Parser)] | ||
pub struct Args { | ||
/// Path to the pest grammar file. | ||
grammar_file_path: PathBuf, | ||
/// Rule name (from the pest grammar file) used to parse program files. | ||
rule_name: String, | ||
/// Paths to program files to parse with the pest grammar. | ||
program_file_paths: Vec<PathBuf>, | ||
} | ||
|
||
fn main() { | ||
let args = Args::parse(); | ||
compile_grammar_and_parse(args); | ||
} | ||
|
||
fn compile_grammar_and_parse(args: Args) { | ||
let mut pie = Pie::with_tracker(WritingTracker::with_stderr()); | ||
|
||
let mut session = pie.new_session(); | ||
let mut errors = String::new(); | ||
|
||
let compile_grammar_task = Tasks::compile_grammar(&args.grammar_file_path); | ||
if let Err(error) = session.require(&compile_grammar_task) { | ||
let _ = writeln!(errors, "{}", error); // Ignore error: writing to String cannot fail. | ||
} | ||
|
||
for path in args.program_file_paths { | ||
let task = Tasks::parse(&compile_grammar_task, &path, &args.rule_name); | ||
match session.require(&task) { | ||
Err(error) => { let _ = writeln!(errors, "{}", error); } | ||
Ok(Outputs::Parsed(Some(output))) => println!("Parsing '{}' succeeded: {}", path.display(), output), | ||
_ => {} | ||
} | ||
} | ||
|
||
if !errors.is_empty() { | ||
println!("Errors:\n{}", errors); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
use std::io; | ||
|
||
use crossterm::event::{DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind}; | ||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}; | ||
use ratatui::backend::{Backend, CrosstermBackend}; | ||
use ratatui::Terminal; | ||
use ratatui::widgets::Paragraph; | ||
|
||
use crate::Args; | ||
|
||
/// Live parser development editor. | ||
pub struct Editor {} | ||
|
||
impl Editor { | ||
/// Create a new editor from `args`. | ||
pub fn new(_args: Args) -> Result<Self, io::Error> { | ||
Ok(Self {}) | ||
} | ||
|
||
/// Run the editor, drawing it into an alternate screen of the terminal. | ||
pub fn run(&mut self) -> Result<(), io::Error> { | ||
// Setup terminal for GUI rendering. | ||
enable_raw_mode()?; | ||
let mut backend = CrosstermBackend::new(io::stdout()); | ||
crossterm::execute!(backend, EnterAlternateScreen, EnableMouseCapture)?; | ||
let mut terminal = Terminal::new(backend)?; | ||
terminal.clear()?; | ||
|
||
// Draw and process events in a loop until a quit is requested or an error occurs. | ||
let result = loop { | ||
match self.draw_and_process_event(&mut terminal) { | ||
Ok(false) => break Ok(()), // Quit requested | ||
Err(e) => break Err(e), // Error | ||
_ => {}, | ||
} | ||
}; | ||
|
||
// First undo our changes to the terminal. | ||
disable_raw_mode()?; | ||
crossterm::execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?; | ||
terminal.show_cursor()?; | ||
// Then present the result to the user. | ||
result | ||
} | ||
|
||
fn draw_and_process_event<B: Backend>(&mut self, terminal: &mut Terminal<B>) -> Result<bool, io::Error> { | ||
terminal.draw(|frame| { | ||
frame.render_widget(Paragraph::new("Hello World! Press Esc to exit."), frame.size()); | ||
})?; | ||
|
||
match crossterm::event::read()? { | ||
Event::Key(key) if key.kind == KeyEventKind::Release => return Ok(true), // Skip releases. | ||
Event::Key(key) if key.code == KeyCode::Esc => return Ok(false), | ||
_ => {} | ||
}; | ||
|
||
Ok(true) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
use std::fmt::Write; | ||
use std::io; | ||
use std::path::PathBuf; | ||
|
||
use clap::Parser; | ||
|
||
use pie::Pie; | ||
use pie::tracker::writing::WritingTracker; | ||
|
||
use crate::editor::Editor; | ||
use crate::task::{Outputs, Tasks}; | ||
|
||
pub mod parse; | ||
pub mod task; | ||
pub mod editor; | ||
|
||
#[derive(Parser)] | ||
struct Cli { | ||
/// Start an interactive parser development editor. | ||
#[arg(short, long)] | ||
edit: bool, | ||
#[command(flatten)] | ||
args: Args, | ||
} | ||
|
||
#[derive(Parser)] | ||
pub struct Args { | ||
/// Path to the pest grammar file. | ||
grammar_file_path: PathBuf, | ||
/// Rule name (from the pest grammar file) used to parse program files. | ||
rule_name: String, | ||
/// Paths to program files to parse with the pest grammar. | ||
program_file_paths: Vec<PathBuf>, | ||
} | ||
|
||
fn main() -> Result<(), io::Error> { | ||
let cli = Cli::parse(); | ||
if cli.edit { | ||
let mut editor = Editor::new(cli.args)?; | ||
editor.run() | ||
} else { | ||
compile_grammar_and_parse(cli.args); | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn compile_grammar_and_parse(args: Args) { | ||
let mut pie = Pie::with_tracker(WritingTracker::with_stderr()); | ||
|
||
let mut session = pie.new_session(); | ||
let mut errors = String::new(); | ||
|
||
let compile_grammar_task = Tasks::compile_grammar(&args.grammar_file_path); | ||
if let Err(error) = session.require(&compile_grammar_task) { | ||
let _ = writeln!(errors, "{}", error); // Ignore error: writing to String cannot fail. | ||
} | ||
|
||
for path in args.program_file_paths { | ||
let task = Tasks::parse(&compile_grammar_task, &path, &args.rule_name); | ||
match session.require(&task) { | ||
Err(error) => { let _ = writeln!(errors, "{}", error); } | ||
Ok(Outputs::Parsed(Some(output))) => println!("Parsing '{}' succeeded: {}", path.display(), output), | ||
_ => {} | ||
} | ||
} | ||
|
||
if !errors.is_empty() { | ||
println!("Errors:\n{}", errors); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters