From 6b42f8b8deda03a27bc2fb1ebe6ab13430dcf7f5 Mon Sep 17 00:00:00 2001 From: greg Date: Sat, 20 Oct 2018 14:27:00 -0700 Subject: [PATCH] Change how parsing works --- schala-lang/language/src/eval.rs | 13 +++++++-- schala-lang/language/src/lib.rs | 14 ++++++++-- schala-lang/language/src/parsing.rs | 43 +++++++++++++++-------------- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/schala-lang/language/src/eval.rs b/schala-lang/language/src/eval.rs index 3fa5a6d..3d5c6fe 100644 --- a/schala-lang/language/src/eval.rs +++ b/schala-lang/language/src/eval.rs @@ -436,17 +436,24 @@ fn case_match_expression(&mut self, cond: Expr, alternatives: Vec) mod eval_tests { use std::cell::RefCell; use std::rc::Rc; + + use tokenizing::{Token, tokenize}; + use ::parsing::ParseResult; + use ::ast::AST; use symbol_table::SymbolTable; - use tokenizing::tokenize; - use parsing::parse; use eval::State; + fn parse(tokens: Vec) -> ParseResult { + let mut parser = ::parsing::Parser::new(tokens); + parser.program() + } + macro_rules! all_output { ($string:expr) => { { let symbol_table = Rc::new(RefCell::new(SymbolTable::new())); let mut state = State::new(symbol_table); - let ast = parse(tokenize($string)).0.unwrap(); + let ast = parse(tokenize($string)).unwrap(); state.symbol_table_handle.borrow_mut().add_top_level_symbols(&ast).unwrap(); let reduced = ast.reduce(&state.symbol_table_handle.borrow()); let all_output = state.evaluate(reduced, true); diff --git a/schala-lang/language/src/lib.rs b/schala-lang/language/src/lib.rs index ba7f562..480da11 100644 --- a/schala-lang/language/src/lib.rs +++ b/schala-lang/language/src/lib.rs @@ -44,6 +44,7 @@ mod eval; pub struct Schala { state: eval::State<'static>, symbol_table: Rc>, + active_parser: Option, } impl Schala { @@ -62,6 +63,7 @@ impl Schala { Schala { symbol_table: symbols.clone(), state: eval::State::new(symbols), + active_parser: None, } } @@ -92,9 +94,17 @@ fn tokenizing(_handle: &mut Schala, input: &str, comp: Option<&mut UnfinishedCom } } -fn parsing(_handle: &mut Schala, input: Vec, comp: Option<&mut UnfinishedComputation>) -> Result { +fn parsing(handle: &mut Schala, input: Vec, comp: Option<&mut UnfinishedComputation>) -> Result { + use parsing::Parser; + + let mut parser = match handle.active_parser.take() { + None => Parser::new(input), + Some(parser) => parser + }; + + let ast = parser.program(); + let trace = parser.format_parse_trace(); - let (ast, trace) = parsing::parse(input); comp.map(|comp| { //TODO need to control which of these debug stages get added let opt = comp.cur_debug_options.get(0).map(|s| s.clone()); diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 4aab248..33b1a7a 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -34,7 +34,7 @@ pub struct ParseRecord { level: u32, } -struct Parser { +pub struct Parser { tokens: Peekable>, parse_record: Vec, parse_level: u32, @@ -46,7 +46,7 @@ struct ParserRestrictions { } impl Parser { - fn new(input: Vec) -> Parser { + pub fn new(input: Vec) -> Parser { Parser { tokens: input.into_iter().peekable(), parse_record: vec![], @@ -64,6 +64,16 @@ impl Parser { fn next(&mut self) -> TokenType { self.tokens.next().map(|ref t| { t.token_type.clone() }).unwrap_or(TokenType::EOF) } + + pub fn format_parse_trace(self) -> Vec { + self.parse_record.into_iter().map(|r| { + let mut indent = String::new(); + for _ in 0..r.level { + indent.push(' '); + } + format!("{}Production `{}`, token: {}", indent, r.production_name, r.next_token) + }).collect() + } } macro_rules! print_token_pattern { @@ -240,8 +250,9 @@ enumerator := identifier '<-' expression | identifier '=' expression //TODO add */ impl Parser { + //TODO make this a proper public interface #[recursive_descent_method] - fn program(&mut self) -> ParseResult { + pub fn program(&mut self) -> ParseResult { let mut statements = Vec::new(); loop { match self.peek() { @@ -1034,24 +1045,11 @@ fn parse_hex(digits: String) -> ParseResult { Ok(result) } -pub fn parse(input: Vec) -> (Result, Vec) { - let mut parser = Parser::new(input); - let ast = parser.program(); - - let trace = parser.parse_record.into_iter().map(|r| { - let mut indent = String::new(); - for _ in 0..r.level { - indent.push(' '); - } - format!("{}Production `{}`, token: {}", indent, r.production_name, r.next_token) - }).collect(); - (ast, trace) -} - #[cfg(test)] mod parse_tests { use ::std::rc::Rc; - use super::{parse, tokenize}; + use super::tokenize; + use super::ParseResult; use builtin::{PrefixOp, BinOp}; use ast::{AST, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody}; use super::Statement::*; @@ -1063,14 +1061,19 @@ mod parse_tests { use super::Variant::*; use super::ForBody::*; + fn parse(tokens: Vec<::tokenizing::Token>) -> ParseResult { + let mut parser = super::Parser::new(tokens); + parser.program() + } + macro_rules! rc { ($string:tt) => { Rc::new(stringify!($string).to_string()) } } macro_rules! parse_test { - ($string:expr, $correct:expr) => { assert_eq!(parse(tokenize($string)).0.unwrap(), $correct) } + ($string:expr, $correct:expr) => { assert_eq!(parse(tokenize($string)).unwrap(), $correct) } } macro_rules! parse_error { - ($string:expr) => { assert!(parse(tokenize($string)).0.is_err()) } + ($string:expr) => { assert!(parse(tokenize($string)).is_err()) } } macro_rules! val { ($var:expr) => { Value(Rc::new($var.to_string())) }