有什么方法可以在 Dart 中按前序、后序或中序遍历 Ast
Is there any way to traverse the Ast in preorder, postorder or Inorder in Dart
有什么方法可以遍历 PreOrder、postOrder 或 inOrder.i 中由 dart Analyzer 组成的 AST,我正在使用访问节点使用 GeneralizingAstVisitor 遍历 AST 树,但它只是从上到下递归地遍历它代码。
import'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/analyzer.dart';
import 'dart:io';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/source/source_resource.dart';
main() {
LibraryElement libElement;
Source source;
AnalysisContext context;
var ast = parseCompilationUnit(src,
parseFunctionBodies: true, suppressErrors: true);
print(ast.toSource());
PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
DartSdk sdk = new FolderBasedDartSdk(resourceProvider,
resourceProvider.getFolder("/usr/local/opt/dart/libexec"));
var resolvers = [
new DartUriResolver(sdk),
];
context = AnalysisEngine.instance.createAnalysisContext()
..sourceFactory = new SourceFactory(resolvers);
source = new FileSource(resourceProvider.getFile(
"/Users/shubhamkumar/Sites/projects/flutterX/dart_analyser/demo.dart"));
ChangeSet changeSet = new ChangeSet()..addedSource(source);
context.applyChanges(changeSet);
libElement = context.computeLibraryElement(source);
callAST(context, source, libElement);
}
class Visitor1 extends GeneralizingAstVisitor {
@override
visitNode(AstNode node) {
print("node $node ${node.runtimeType} ");
node.childEntities.forEach((n) => print(n));
return super.visitNode(node);
}
}
callAST(context, source, libElement) {
CompilationUnit resolvedUnit =
context.resolveCompilationUnit(source, libElement);
var visitor = new Visitor1();
resolvedUnit.accept(visitor);
}
有解决办法请帮忙
GeneralizingAstVisitor 执行的模式是 pre-order。
In-order 遍历在 AST 的上下文中没有意义。 In-order遍历是左、根、右。但是 AST 分支可能有从 1 到无穷大 children 的任何地方。所以你能做的最好的事情就是定义一些 in-order(n) 遍历,在那里你访问第一个 child、第二个 child、... nth-child、root、nth+ 1 child, nth+2 child...我看不出这样做的目的。
对于 post-order 它有点细微差别。如果您只想打印节点及其 child 实体,那么您的解决方案很简单。您只需要在 打印节点之前调用 super :
class Visitor2 extends GeneralizingAstVisitor {
@override
visitNode(AstNode node) {
final val = super.visitNode(node);
print("node $node ${node.runtimeType} ");
node.childEntities.forEach((n) => print(n));
return val;
}
}
但是如果你想为一堆节点类型定制逻辑,你必须在每个访问处理程序中遵循该模式:
class Visitor3 extends GeneralizingAstVisitor {
@override
visitAssignmentExpression(AssignmentExpression node) {
final val = super.visitNode(node);
// use assignment expression here
return val;
}
@override
visitBinaryExpression(BinaryExpression node) {
final val = super.visitNode(node);
// use binary expression here
return val;
}
// ... more handlers
}
在这种情况下,我会编写访客以使其更容易:
class PostOrderVisitor extends GeneralizingAstVisitor {
AstVisitor postOrderedVisitor = new Visitor4();
@override
visitNode(AstNode node) {
final val = super.visitNode(node);
return node.accept(postOrderedVisitor);
}
}
class Visitor4 extends AstVisitor {
@override
visitAssignmentExpression(AssignmentExpression node) {
// use assignment expression here
}
@override
visitBinaryExpression(BinaryExpression node) {
// use binary expression here
}
// ... more handlers
}
在这种情况下,PostOrderVisitor
处理 post-ordering,Visitor4
根据该顺序处理各个节点,但本身不应执行任何递归。
对于大多数用例,这些应该可以帮助您,尽管在不知道您要做什么的情况下很难确定。
有什么方法可以遍历 PreOrder、postOrder 或 inOrder.i 中由 dart Analyzer 组成的 AST,我正在使用访问节点使用 GeneralizingAstVisitor 遍历 AST 树,但它只是从上到下递归地遍历它代码。
import'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/analyzer.dart';
import 'dart:io';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/source/source_resource.dart';
main() {
LibraryElement libElement;
Source source;
AnalysisContext context;
var ast = parseCompilationUnit(src,
parseFunctionBodies: true, suppressErrors: true);
print(ast.toSource());
PhysicalResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
DartSdk sdk = new FolderBasedDartSdk(resourceProvider,
resourceProvider.getFolder("/usr/local/opt/dart/libexec"));
var resolvers = [
new DartUriResolver(sdk),
];
context = AnalysisEngine.instance.createAnalysisContext()
..sourceFactory = new SourceFactory(resolvers);
source = new FileSource(resourceProvider.getFile(
"/Users/shubhamkumar/Sites/projects/flutterX/dart_analyser/demo.dart"));
ChangeSet changeSet = new ChangeSet()..addedSource(source);
context.applyChanges(changeSet);
libElement = context.computeLibraryElement(source);
callAST(context, source, libElement);
}
class Visitor1 extends GeneralizingAstVisitor {
@override
visitNode(AstNode node) {
print("node $node ${node.runtimeType} ");
node.childEntities.forEach((n) => print(n));
return super.visitNode(node);
}
}
callAST(context, source, libElement) {
CompilationUnit resolvedUnit =
context.resolveCompilationUnit(source, libElement);
var visitor = new Visitor1();
resolvedUnit.accept(visitor);
}
有解决办法请帮忙
GeneralizingAstVisitor 执行的模式是 pre-order。
In-order 遍历在 AST 的上下文中没有意义。 In-order遍历是左、根、右。但是 AST 分支可能有从 1 到无穷大 children 的任何地方。所以你能做的最好的事情就是定义一些 in-order(n) 遍历,在那里你访问第一个 child、第二个 child、... nth-child、root、nth+ 1 child, nth+2 child...我看不出这样做的目的。
对于 post-order 它有点细微差别。如果您只想打印节点及其 child 实体,那么您的解决方案很简单。您只需要在 打印节点之前调用 super :
class Visitor2 extends GeneralizingAstVisitor {
@override
visitNode(AstNode node) {
final val = super.visitNode(node);
print("node $node ${node.runtimeType} ");
node.childEntities.forEach((n) => print(n));
return val;
}
}
但是如果你想为一堆节点类型定制逻辑,你必须在每个访问处理程序中遵循该模式:
class Visitor3 extends GeneralizingAstVisitor {
@override
visitAssignmentExpression(AssignmentExpression node) {
final val = super.visitNode(node);
// use assignment expression here
return val;
}
@override
visitBinaryExpression(BinaryExpression node) {
final val = super.visitNode(node);
// use binary expression here
return val;
}
// ... more handlers
}
在这种情况下,我会编写访客以使其更容易:
class PostOrderVisitor extends GeneralizingAstVisitor {
AstVisitor postOrderedVisitor = new Visitor4();
@override
visitNode(AstNode node) {
final val = super.visitNode(node);
return node.accept(postOrderedVisitor);
}
}
class Visitor4 extends AstVisitor {
@override
visitAssignmentExpression(AssignmentExpression node) {
// use assignment expression here
}
@override
visitBinaryExpression(BinaryExpression node) {
// use binary expression here
}
// ... more handlers
}
在这种情况下,PostOrderVisitor
处理 post-ordering,Visitor4
根据该顺序处理各个节点,但本身不应执行任何递归。
对于大多数用例,这些应该可以帮助您,尽管在不知道您要做什么的情况下很难确定。