diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs
index b988b348cd..64b97b6bb4 100644
--- a/compiler/ast/src/lib.rs
+++ b/compiler/ast/src/lib.rs
@@ -43,12 +43,12 @@ pub use self::input::*;
pub mod pass;
pub use self::pass::*;
+pub mod passes;
+pub use self::passes::*;
+
pub mod program;
pub use self::program::*;
-pub mod reducer;
-pub use self::reducer::*;
-
pub mod statements;
pub use self::statements::*;
diff --git a/compiler/ast/src/reducer/mod.rs b/compiler/ast/src/passes/mod.rs
similarity index 75%
rename from compiler/ast/src/reducer/mod.rs
rename to compiler/ast/src/passes/mod.rs
index 87d296ee02..98f524e338 100644
--- a/compiler/ast/src/reducer/mod.rs
+++ b/compiler/ast/src/passes/mod.rs
@@ -14,13 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-//! This module contains both a Director to reconstruct the AST
-//! which maps over every node of the AST and calls a reducer.
-//! The Trait for a reducer are methods that can be overridden
-//! to make changes to how AST nodes are rebuilt.
+//! This module contains both a Reducer and Visitor design pattern.
+//! These both iterate over the AST.
+
+// todo @gluax: Move the files in this module into `leo-passes` in a future PR.
pub mod reconstructing_reducer;
pub use reconstructing_reducer::*;
pub mod reconstructing_director;
pub use reconstructing_director::*;
+
+pub mod visitor;
+pub use visitor::*;
+
+pub mod visitor_director;
+pub use visitor_director::*;
diff --git a/compiler/ast/src/reducer/reconstructing_director.rs b/compiler/ast/src/passes/reconstructing_director.rs
similarity index 100%
rename from compiler/ast/src/reducer/reconstructing_director.rs
rename to compiler/ast/src/passes/reconstructing_director.rs
diff --git a/compiler/ast/src/reducer/reconstructing_reducer.rs b/compiler/ast/src/passes/reconstructing_reducer.rs
similarity index 100%
rename from compiler/ast/src/reducer/reconstructing_reducer.rs
rename to compiler/ast/src/passes/reconstructing_reducer.rs
diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs
new file mode 100644
index 0000000000..c7b64f5bfa
--- /dev/null
+++ b/compiler/ast/src/passes/visitor.rs
@@ -0,0 +1,112 @@
+// Copyright (C) 2019-2022 Aleo Systems Inc.
+// This file is part of the Leo library.
+
+// The Leo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// The Leo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with the Leo library. If not, see .
+
+//! This module contains Visitor traits for the AST.
+
+use crate::*;
+
+pub enum VisitResult {
+ VisitChildren,
+ SkipChildren,
+}
+
+impl Default for VisitResult {
+ fn default() -> Self {
+ VisitResult::VisitChildren
+ }
+}
+
+pub trait ExpressionVisitor {
+ fn visit_expression(&mut self, _input: &Expression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_identifer(&mut self, _input: &Identifier) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_value(&mut self, _input: &ValueExpression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_binary(&mut self, _input: &BinaryExpression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_unary(&mut self, _input: &UnaryExpression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_ternary(&mut self, _input: &TernaryExpression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_call(&mut self, _input: &CallExpression) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_err(&mut self, _input: &ErrExpression) -> VisitResult {
+ Default::default()
+ }
+}
+
+pub trait StatementVisitor {
+ fn visit_statement(&mut self, _input: &Statement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_return(&mut self, _input: &ReturnStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_definition(&mut self, _input: &DefinitionStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_assign(&mut self, _input: &AssignStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_conditional(&mut self, _input: &ConditionalStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_iteration(&mut self, _input: &IterationStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_console(&mut self, _input: &ConsoleStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_expression_statement(&mut self, _input: &ExpressionStatement) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_block(&mut self, _input: &Block) -> VisitResult {
+ Default::default()
+ }
+}
+
+pub trait ProgramVisitor {
+ fn visit_program(&mut self, _input: &Program) -> VisitResult {
+ Default::default()
+ }
+
+ fn visit_function(&mut self, _input: &Function) -> VisitResult {
+ Default::default()
+ }
+}
diff --git a/compiler/ast/src/passes/visitor_director.rs b/compiler/ast/src/passes/visitor_director.rs
new file mode 100644
index 0000000000..45e7188d22
--- /dev/null
+++ b/compiler/ast/src/passes/visitor_director.rs
@@ -0,0 +1,170 @@
+// Copyright (C) 2019-2022 Aleo Systems Inc.
+// This file is part of the Leo library.
+
+// The Leo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// The Leo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with the Leo library. If not, see .
+
+//! This module contains Visitor trait implementations for the AST.
+//! It implements default methods for each node to be made
+//! given the type of node its visiting.
+
+// temporary till we use in another pr.
+#![allow(dead_code)]
+
+use crate::*;
+
+pub struct VisitorDirector {
+ visitor: V,
+}
+
+impl VisitorDirector {
+ pub fn new(visitor: V) -> Self {
+ Self { visitor }
+ }
+
+ pub fn visitor(self) -> V {
+ self.visitor
+ }
+
+ pub fn visit_expression(&mut self, input: &Expression) {
+ if let VisitResult::VisitChildren = self.visitor.visit_expression(input) {
+ match input {
+ Expression::Identifier(_) => {}
+ Expression::Value(_) => {}
+ Expression::Binary(expr) => self.visit_binary(expr),
+ Expression::Unary(expr) => self.visit_unary(expr),
+ Expression::Ternary(expr) => self.visit_ternary(expr),
+ Expression::Call(expr) => self.visit_call(expr),
+ Expression::Err(_) => {}
+ }
+ }
+ }
+
+ pub fn visit_binary(&mut self, input: &BinaryExpression) {
+ if let VisitResult::VisitChildren = self.visitor.visit_binary(input) {
+ self.visit_expression(&input.left);
+ self.visit_expression(&input.right);
+ }
+ }
+
+ pub fn visit_unary(&mut self, input: &UnaryExpression) {
+ if let VisitResult::VisitChildren = self.visitor.visit_unary(input) {
+ self.visit_expression(&input.inner);
+ }
+ }
+
+ pub fn visit_ternary(&mut self, input: &TernaryExpression) {
+ if let VisitResult::VisitChildren = self.visitor.visit_ternary(input) {
+ self.visit_expression(&input.condition);
+ self.visit_expression(&input.if_true);
+ self.visit_expression(&input.if_false);
+ }
+ }
+
+ pub fn visit_call(&mut self, input: &CallExpression) {
+ if let VisitResult::VisitChildren = self.visitor.visit_call(input) {
+ self.visit_expression(&input.function);
+ input.arguments.iter().for_each(|expr| self.visit_expression(expr));
+ }
+ }
+}
+
+impl VisitorDirector {
+ fn visit_statement(&mut self, input: &Statement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_statement(input) {
+ match input {
+ Statement::Return(stmt) => self.visit_return(stmt),
+ Statement::Definition(stmt) => self.visit_definition(stmt),
+ Statement::Assign(stmt) => self.visit_assign(stmt),
+ Statement::Conditional(stmt) => self.visit_conditional(stmt),
+ Statement::Iteration(stmt) => self.visit_iteration(stmt),
+ Statement::Console(stmt) => self.visit_console(stmt),
+ Statement::Expression(stmt) => self.visit_expression_statement(stmt),
+ Statement::Block(stmt) => self.visit_block(stmt),
+ }
+ }
+ }
+
+ fn visit_return(&mut self, input: &ReturnStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_return(input) {
+ self.visit_expression(&input.expression);
+ }
+ }
+
+ fn visit_definition(&mut self, input: &DefinitionStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_definition(input) {
+ self.visit_expression(&input.value);
+ }
+ }
+
+ fn visit_assign(&mut self, input: &AssignStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_assign(input) {
+ self.visit_expression(&input.value);
+ }
+ }
+
+ fn visit_conditional(&mut self, input: &ConditionalStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_conditional(input) {
+ self.visit_expression(&input.condition);
+ self.visit_block(&input.block);
+ if let Some(stmt) = input.next.as_ref() {
+ self.visit_statement(stmt);
+ }
+ }
+ }
+
+ fn visit_iteration(&mut self, input: &IterationStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_iteration(input) {
+ self.visit_expression(&input.start);
+ self.visit_expression(&input.stop);
+ self.visit_block(&input.block);
+ }
+ }
+
+ fn visit_console(&mut self, input: &ConsoleStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_console(input) {
+ if let ConsoleFunction::Assert(expr) = &input.function {
+ self.visit_expression(expr);
+ }
+ }
+ }
+
+ fn visit_expression_statement(&mut self, input: &ExpressionStatement) {
+ if let VisitResult::VisitChildren = self.visitor.visit_expression_statement(input) {
+ self.visit_expression(&input.expression);
+ }
+ }
+
+ fn visit_block(&mut self, input: &Block) {
+ if let VisitResult::VisitChildren = self.visitor.visit_block(input) {
+ input.statements.iter().for_each(|stmt| self.visit_statement(stmt));
+ }
+ }
+}
+
+impl VisitorDirector {
+ fn visit_program(&mut self, input: &Program) {
+ if let VisitResult::VisitChildren = self.visitor.visit_program(input) {
+ input
+ .functions
+ .values()
+ .for_each(|function| self.visit_function(function));
+ }
+ }
+
+ fn visit_function(&mut self, input: &Function) {
+ if let VisitResult::VisitChildren = self.visitor.visit_function(input) {
+ self.visit_block(&input.block);
+ }
+ }
+}
diff --git a/compiler/parser/src/tokenizer/lexer.rs b/compiler/parser/src/tokenizer/lexer.rs
index 45ced2d423..8d48cbbd94 100644
--- a/compiler/parser/src/tokenizer/lexer.rs
+++ b/compiler/parser/src/tokenizer/lexer.rs
@@ -46,7 +46,7 @@ fn eat_identifier(input: &mut Peekable>) -> Option bool {
let i = c as u32;
- return (0x202A <= i && i <= 0x202E) || (0x2066 <= i && i <= 0x2069);
+ (0x202A..=0x202E).contains(&i) || (0x2066..=0x2069).contains(&i)
}
impl Token {
diff --git a/docs/grammar/README.md b/docs/grammar/README.md
index e4a8a9f6e9..44c9f6b666 100644
Binary files a/docs/grammar/README.md and b/docs/grammar/README.md differ