Refactor.

This commit is contained in:
Stephen Chung 2020-06-03 10:44:36 +08:00
parent b8da1691d3
commit ec6e3daabb
2 changed files with 53 additions and 79 deletions

@ -7,7 +7,7 @@ use crate::fn_call::FuncArgs;
use crate::fn_native::{IteratorFn, SendSync}; use crate::fn_native::{IteratorFn, SendSync};
use crate::fn_register::RegisterFn; use crate::fn_register::RegisterFn;
use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::optimize::{optimize_into_ast, OptimizationLevel};
use crate::parser::{parse, parse_global_expr, AST}; use crate::parser::AST;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::scope::Scope; use crate::scope::Scope;
use crate::token::{lex, Position}; use crate::token::{lex, Position};
@ -449,14 +449,7 @@ impl Engine {
optimization_level: OptimizationLevel, optimization_level: OptimizationLevel,
) -> Result<AST, ParseError> { ) -> Result<AST, ParseError> {
let stream = lex(scripts); let stream = lex(scripts);
self.parse(&mut stream.peekable(), scope, optimization_level)
parse(
&mut stream.peekable(),
self,
scope,
optimization_level,
(self.max_expr_depth, self.max_function_expr_depth),
)
} }
/// Read the contents of a file into a string. /// Read the contents of a file into a string.
@ -578,13 +571,8 @@ impl Engine {
// Trims the JSON string and add a '#' in front // Trims the JSON string and add a '#' in front
let scripts = ["#", json.trim()]; let scripts = ["#", json.trim()];
let stream = lex(&scripts); let stream = lex(&scripts);
let ast = parse_global_expr( let ast =
&mut stream.peekable(), self.parse_global_expr(&mut stream.peekable(), &scope, OptimizationLevel::None)?;
self,
&scope,
OptimizationLevel::None,
self.max_expr_depth,
)?;
// Handle null - map to () // Handle null - map to ()
if has_null { if has_null {
@ -667,13 +655,7 @@ impl Engine {
{ {
let mut peekable = stream.peekable(); let mut peekable = stream.peekable();
parse_global_expr( self.parse_global_expr(&mut peekable, scope, self.optimization_level)
&mut peekable,
self,
scope,
self.optimization_level,
self.max_expr_depth,
)
} }
} }
@ -825,12 +807,10 @@ impl Engine {
let scripts = [script]; let scripts = [script];
let stream = lex(&scripts); let stream = lex(&scripts);
let ast = parse_global_expr( let ast = self.parse_global_expr(
&mut stream.peekable(), &mut stream.peekable(),
self,
scope, scope,
OptimizationLevel::None, // No need to optimize a lone expression OptimizationLevel::None, // No need to optimize a lone expression
self.max_expr_depth,
)?; )?;
self.eval_ast_with_scope(scope, &ast) self.eval_ast_with_scope(scope, &ast)
@ -957,13 +937,7 @@ impl Engine {
let scripts = [script]; let scripts = [script];
let stream = lex(&scripts); let stream = lex(&scripts);
let ast = parse( let ast = self.parse(&mut stream.peekable(), scope, self.optimization_level)?;
&mut stream.peekable(),
self,
scope,
self.optimization_level,
(self.max_expr_depth, self.max_function_expr_depth),
)?;
self.consume_ast_with_scope(scope, &ast) self.consume_ast_with_scope(scope, &ast)
} }

@ -2478,44 +2478,15 @@ fn parse_fn<'a>(
}) })
} }
pub fn parse_global_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>,
engine: &Engine,
scope: &Scope,
optimization_level: OptimizationLevel,
max_expr_depth: usize,
) -> Result<AST, ParseError> {
let mut state = ParseState::new(max_expr_depth);
let expr = parse_expr(input, &mut state, 0, false, false)?;
match input.peek().unwrap() {
(Token::EOF, _) => (),
// Return error if the expression doesn't end
(token, pos) => {
return Err(PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(*pos))
}
}
Ok(
// Optimize AST
optimize_into_ast(
engine,
scope,
vec![Stmt::Expr(Box::new(expr))],
vec![],
optimization_level,
),
)
}
/// Parse the global level statements. /// Parse the global level statements.
fn parse_global_level<'a>( fn parse_global_level<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
max_expr_depth: (usize, usize), max_expr_depth: usize,
max_function_expr_depth: usize,
) -> Result<(Vec<Stmt>, Vec<FnDef>), ParseError> { ) -> Result<(Vec<Stmt>, Vec<FnDef>), ParseError> {
let mut statements = Vec::<Stmt>::new(); let mut statements = Vec::<Stmt>::new();
let mut functions = HashMap::<u64, FnDef, _>::with_hasher(StraightHasherBuilder); let mut functions = HashMap::<u64, FnDef, _>::with_hasher(StraightHasherBuilder);
let mut state = ParseState::new(max_expr_depth.0); let mut state = ParseState::new(max_expr_depth);
while !input.peek().unwrap().0.is_eof() { while !input.peek().unwrap().0.is_eof() {
// Collect all the function definitions // Collect all the function definitions
@ -2530,7 +2501,7 @@ fn parse_global_level<'a>(
match input.peek().unwrap() { match input.peek().unwrap() {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
(Token::Fn, _) => { (Token::Fn, _) => {
let mut state = ParseState::new(max_expr_depth.1); let mut state = ParseState::new(max_function_expr_depth);
let func = parse_fn(input, &mut state, access, 0, true, true)?; let func = parse_fn(input, &mut state, access, 0, true, true)?;
// Qualifiers (none) + function name + number of arguments. // Qualifiers (none) + function name + number of arguments.
@ -2586,20 +2557,49 @@ fn parse_global_level<'a>(
Ok((statements, functions.into_iter().map(|(_, v)| v).collect())) Ok((statements, functions.into_iter().map(|(_, v)| v).collect()))
} }
/// Run the parser on an input stream, returning an AST. impl Engine {
pub fn parse<'a>( pub(crate) fn parse_global_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>, &self,
engine: &Engine, input: &mut Peekable<TokenIterator<'a>>,
scope: &Scope, scope: &Scope,
optimization_level: OptimizationLevel, optimization_level: OptimizationLevel,
max_expr_depth: (usize, usize), ) -> Result<AST, ParseError> {
) -> Result<AST, ParseError> { let mut state = ParseState::new(self.max_expr_depth);
let (statements, lib) = parse_global_level(input, max_expr_depth)?; let expr = parse_expr(input, &mut state, 0, false, false)?;
Ok( match input.peek().unwrap() {
// Optimize AST (Token::EOF, _) => (),
optimize_into_ast(engine, scope, statements, lib, optimization_level), // Return error if the expression doesn't end
) (token, pos) => {
return Err(
PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(*pos)
)
}
}
let expr = vec![Stmt::Expr(Box::new(expr))];
Ok(
// Optimize AST
optimize_into_ast(self, scope, expr, Default::default(), optimization_level),
)
}
/// Run the parser on an input stream, returning an AST.
pub(crate) fn parse<'a>(
&self,
input: &mut Peekable<TokenIterator<'a>>,
scope: &Scope,
optimization_level: OptimizationLevel,
) -> Result<AST, ParseError> {
let (statements, lib) =
parse_global_level(input, self.max_expr_depth, self.max_function_expr_depth)?;
Ok(
// Optimize AST
optimize_into_ast(self, scope, statements, lib, optimization_level),
)
}
} }
/// Map a `Dynamic` value to an expression. /// Map a `Dynamic` value to an expression.