diff --git a/lyt/src/ast.rs b/lyt/src/ast.rs index e4d1177..efbacf0 100644 --- a/lyt/src/ast.rs +++ b/lyt/src/ast.rs @@ -14,3 +14,5 @@ pub enum Expression { Integer(i64), Unit, } + +impl Expression {} diff --git a/lyt/src/cli.rs b/lyt/src/cli.rs index 433e464..93ba42f 100644 --- a/lyt/src/cli.rs +++ b/lyt/src/cli.rs @@ -1,4 +1,12 @@ -use std::str::FromStr; +use std::{ + io::{self, Write}, + str::FromStr, +}; + +use crate::{ + lexer::{self, Lexer, Source, Token}, + parser::Parser, +}; struct GlobalArgs { subcommand: Option, @@ -44,7 +52,7 @@ fn usage(exit_code: i32) -> ! { fn parse_global_args() -> Result { let mut subcommand = None; - let mut args = std::env::args(); + let mut args = std::env::args().skip(1); while let Some(arg) = args.next() { match arg.as_str() { @@ -61,6 +69,46 @@ fn parse_global_args() -> Result { return Ok(GlobalArgs { subcommand }); } -pub fn run() -> crate::Result<()> { - Ok(()) +fn repl() -> ! { + println!("lytlang repl (^D to stop)"); + print!("> "); + std::io::stdout().flush().expect("failed to flush stdout"); + let mut iter = std::io::stdin().lines().enumerate().into_iter(); + while let Some((i, l)) = iter.next() { + let s = match &l { + Ok(s) => s.as_str(), + Err(e) => { + eprintln!("error reading line from stdin: {}", e); + continue; + } + }; + let tokens = match Lexer::new(s, Source::Repl(i)).collect() { + Ok(tokens) => tokens, + Err(e) => { + eprintln!("error lexing input: {:?}", e); + continue; + } + }; + match Parser::default().parse(tokens) { + Ok(expr) => println!("< {:?}", expr), + Err(e) => { + eprintln!("error parsing tokens: {:?}", e); + continue; + } + } + println!("> "); + std::io::stdout().flush().expect("failed to flush stdout"); + } + std::process::exit(0); +} + +pub fn run() -> crate::Result<()> { + match parse_global_args()?.subcommand { + Some(Subcommand::Repl) => repl(), + Some(Subcommand::Help) => usage(0), + None => { + println!("no subcommand specified"); + usage(1) + } + } } diff --git a/lyt/src/lexer.rs b/lyt/src/lexer.rs index c5e67d7..cec92d0 100644 --- a/lyt/src/lexer.rs +++ b/lyt/src/lexer.rs @@ -29,6 +29,8 @@ pub enum Source { Unknown, File(Arc>), + + Repl(usize), } #[derive(Debug, PartialEq, Clone)] @@ -166,16 +168,12 @@ impl<'a> Lexer<'a> { } } - dbg!(&self.collected); Ok(self.produce(BareToken::Integer( self.collected .iter() .collect::() .parse() - .map_err(|e: ParseIntError| { - dbg!(&e); - self.produce_error(e.into()) - })?, + .map_err(|e: ParseIntError| self.produce_error(e.into()))?, ))) } } @@ -188,6 +186,7 @@ impl<'a> Iterator for Lexer<'a> { return None; } if self.done && !self.sent_eof { + self.sent_eof = true; return Some(Ok(Token { location: None, token: BareToken::EndOfFile, @@ -309,9 +308,10 @@ mod test { t(pos(1), BareToken::Integer(3)), t(pos(3), BareToken::Plus), t(pos(5), BareToken::Integer(9)), + t(Option::None, BareToken::EndOfFile), ]), ); - assert_eq!(tokens?.len(), 3); + assert_eq!(tokens?.len(), 4); Ok(()) } } diff --git a/lyt/src/parser.rs b/lyt/src/parser.rs index a0f7fe5..ffe1b82 100644 --- a/lyt/src/parser.rs +++ b/lyt/src/parser.rs @@ -2,7 +2,7 @@ use std::{iter::Peekable, vec::IntoIter}; use crate::{ast::*, lexer}; -struct Parser { +pub struct Parser { num_tokens_parsed: usize, }