152 lines
3.5 KiB
Rust
152 lines
3.5 KiB
Rust
use std::rc::Rc;
|
|
|
|
use ast::*;
|
|
|
|
pub fn dispatch<T, V: ASTVisitor<T>>(visitor: &mut V, ast: &AST) -> T {
|
|
visitor.ast(ast);
|
|
for statement in ast.0.iter() {
|
|
visitor.statement(statement);
|
|
match statement {
|
|
Statement::ExpressionStatement(expr) => {
|
|
let ref mut expression_visitor = visitor.expression();
|
|
ExpressionVisitor::dispatch(expression_visitor, expr);
|
|
},
|
|
Statement::Declaration(decl) => {
|
|
let ref mut declaration_visitor = visitor.declaration();
|
|
DeclarationVisitor::dispatch(declaration_visitor, decl);
|
|
},
|
|
}
|
|
}
|
|
visitor.done()
|
|
}
|
|
|
|
pub trait ASTVisitor<T> {
|
|
type EV : ExpressionVisitor<T>;
|
|
type DV : DeclarationVisitor<T>;
|
|
|
|
fn ast(&mut self, _ast: &AST) { }
|
|
fn statement(&mut self, _statement: &Statement) { }
|
|
fn expression(&mut self) -> Self::EV;
|
|
fn declaration(&mut self) -> Self::DV;
|
|
fn done(&mut self) -> T;
|
|
}
|
|
|
|
pub trait ExpressionVisitor<T> {
|
|
fn dispatch(visitor: &mut Self, expr: &Expression) -> T {
|
|
visitor.expression(expr);
|
|
visitor.done()
|
|
}
|
|
fn expression(&mut self, _expression: &Expression) { }
|
|
fn done(&mut self) -> T;
|
|
}
|
|
|
|
pub trait DeclarationVisitor<T> {
|
|
fn dispatch(visitor: &mut Self, decl: &Declaration) -> T {
|
|
use self::Declaration::*;
|
|
match decl {
|
|
FuncSig(sig) => visitor.func_signature(sig),
|
|
FuncDecl(sig, block) => visitor.func_declaration(sig, block),
|
|
TypeDecl { name, body, mutable } => visitor.type_declaration(name, body, mutable),
|
|
TypeAlias(alias, name) => visitor.type_alias(alias, name),
|
|
Binding { .. } => unimplemented!(),
|
|
Impl { .. } => unimplemented!(),
|
|
Interface { .. } => unimplemented!(),
|
|
};
|
|
visitor.done()
|
|
}
|
|
|
|
fn declaration(&mut self, _decl: &Declaration) { }
|
|
fn func_signature(&mut self, _sig: &Signature) { }
|
|
fn func_declaration(&mut self, _sig: &Signature, _block: &Vec<Statement>) { }
|
|
fn type_declaration(&mut self, _name: &TypeSingletonName, _body: &TypeBody, _mutable: &bool) { }
|
|
fn type_alias(&mut self, _alias: &Rc<String>, _name: &Rc<String>) { }
|
|
fn done(&mut self) -> T;
|
|
}
|
|
|
|
/*----*/
|
|
|
|
|
|
struct NullVisitor { }
|
|
impl ASTVisitor<()> for NullVisitor {
|
|
type EV = NullVisitor;
|
|
type DV = NullVisitor;
|
|
fn done(&mut self) -> () {
|
|
()
|
|
}
|
|
|
|
fn expression(&mut self) -> Self::EV {
|
|
NullVisitor { }
|
|
}
|
|
|
|
fn declaration(&mut self) -> Self::DV {
|
|
NullVisitor { }
|
|
}
|
|
}
|
|
|
|
impl ExpressionVisitor<()> for NullVisitor {
|
|
fn done(&mut self) -> () {
|
|
()
|
|
}
|
|
}
|
|
|
|
impl DeclarationVisitor<()> for NullVisitor {
|
|
fn done(&mut self) -> () {
|
|
()
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Default, Clone)]
|
|
struct SchalaPrinter {
|
|
s: String
|
|
}
|
|
|
|
impl ASTVisitor<String> for SchalaPrinter {
|
|
type EV = SchalaPrinter;
|
|
type DV = SchalaPrinter;
|
|
fn ast(&mut self, _: &AST) {
|
|
self.s.push_str("Pretty-printed AST");
|
|
}
|
|
|
|
fn expression(&mut self) -> Self::EV {
|
|
SchalaPrinter::default()
|
|
}
|
|
fn declaration(&mut self) -> Self::DV {
|
|
SchalaPrinter::default()
|
|
}
|
|
|
|
fn done(&mut self) -> String {
|
|
self.s.clone()
|
|
}
|
|
}
|
|
|
|
impl ExpressionVisitor<String> for SchalaPrinter {
|
|
fn done(&mut self) -> String {
|
|
format!("some_expr")
|
|
}
|
|
}
|
|
|
|
impl DeclarationVisitor<String> for SchalaPrinter {
|
|
fn done(&mut self) -> String {
|
|
format!("some_decl")
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod visitor_tests {
|
|
use ::tokenizing::{Token, tokenize};
|
|
use ::parsing::ParseResult;
|
|
use ::ast::AST;
|
|
|
|
fn parse(input: &str) -> ParseResult<AST> {
|
|
let tokens = tokenize(input);
|
|
let mut parser = ::parsing::Parser::new(tokens);
|
|
parser.parse()
|
|
}
|
|
|
|
#[test]
|
|
fn test() {
|
|
let q = parse("foo");
|
|
}
|
|
}
|