examples/identify_tokens.rs: Overhaul user experience

This commit is contained in:
John 2023-10-16 22:26:32 -05:00
parent 50bb03ae18
commit 1f0725d2c8

View File

@ -1,16 +1,60 @@
//! This example grabs input from stdin, lexes it, and prints which lexer rules matched //! This example grabs input from stdin, lexes it, and prints which lexer rules matched
#![allow(unused_imports)] #![allow(unused_imports)]
use conlang::lexer::Lexer; use conlang::lexer::Lexer;
use std::{error::Error, io::stdin}; use std::{
error::Error,
io::{stdin, IsTerminal, Read},
path::{Path, PathBuf},
};
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
// get input from stdin let conf = Config::new();
for line in stdin().lines() { if conf.paths.is_empty() {
let line = line?; take_stdin()?;
let mut lexer = Lexer::new(&line); } else {
while let Some(token) = lexer.any() { for path in conf.paths.iter().map(PathBuf::as_path) {
println!("{:#19}{}", token.ty(), &line[token.range()]) lex_tokens(&std::fs::read_to_string(path)?, Some(path));
} }
} }
Ok(()) Ok(())
} }
struct Config {
paths: Vec<PathBuf>,
}
impl Config {
fn new() -> Self {
Config { paths: std::env::args().skip(1).map(PathBuf::from).collect() }
}
}
fn take_stdin() -> Result<(), Box<dyn Error>> {
if stdin().is_terminal() {
for line in stdin().lines() {
lex_tokens(&line?, None)
}
} else {
lex_tokens(&std::io::read_to_string(stdin())?, None)
}
Ok(())
}
fn lex_tokens(file: &str, path: Option<&Path>) {
for token in Lexer::new(file) {
if let Some(path) = path {
print!("{path:?}:")
}
print_token(file, token);
}
}
fn print_token(line: &str, t: conlang::token::Token) {
println!(
"{:02}:{:02}: {:#19} │{}│",
t.line(),
t.col(),
t.ty(),
&line[t.range()]
)
}