Change how parsing works
This commit is contained in:
parent
d9e67a6341
commit
6b42f8b8de
@ -436,17 +436,24 @@ fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>)
|
||||
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<Token>) -> ParseResult<AST> {
|
||||
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);
|
||||
|
@ -44,6 +44,7 @@ mod eval;
|
||||
pub struct Schala {
|
||||
state: eval::State<'static>,
|
||||
symbol_table: Rc<RefCell<symbol_table::SymbolTable>>,
|
||||
active_parser: Option<parsing::Parser>,
|
||||
}
|
||||
|
||||
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<tokenizing::Token>, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
|
||||
fn parsing(handle: &mut Schala, input: Vec<tokenizing::Token>, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
|
||||
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());
|
||||
|
@ -34,7 +34,7 @@ pub struct ParseRecord {
|
||||
level: u32,
|
||||
}
|
||||
|
||||
struct Parser {
|
||||
pub struct Parser {
|
||||
tokens: Peekable<IntoIter<Token>>,
|
||||
parse_record: Vec<ParseRecord>,
|
||||
parse_level: u32,
|
||||
@ -46,7 +46,7 @@ struct ParserRestrictions {
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
fn new(input: Vec<Token>) -> Parser {
|
||||
pub fn new(input: Vec<Token>) -> 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<String> {
|
||||
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<AST> {
|
||||
pub fn program(&mut self) -> ParseResult<AST> {
|
||||
let mut statements = Vec::new();
|
||||
loop {
|
||||
match self.peek() {
|
||||
@ -1034,24 +1045,11 @@ fn parse_hex(digits: String) -> ParseResult<u64> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn parse(input: Vec<Token>) -> (Result<AST, ParseError>, Vec<String>) {
|
||||
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<AST> {
|
||||
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())) }
|
||||
|
Loading…
Reference in New Issue
Block a user