如何在 AST 中查找标识符的用法?
给定以下 AST 定义和示例代码,在给定树中位置的情况下查找标识符的所有用法的最佳算法是什么?
AST Definition
type Literal
= Char of char // character literal
| String of string // string literal
| Integer of int // integer literal
| Float of float // floating point literal
| Double of double
| Unit
type SrcCol = { startColumn : int; endColumn : int }
type SrcLine = { startLine : int; endLine : int }
type SrcLoc = { srcFilename : string; srcLine : SrcLine; srcColumn : SrcCol }
type Pat =
| PVar of 'a
| PApp of Pat * Pat
| PLit of Literal
| PWithTy of Pat * Type
type Exp
= Var of 'a // variable
| Lam of Pat list * Exp // lambda abstraction
| App of Exp * Exp // application
| Let of Pat * Exp * Exp // local definition
| Lit of Literal // literal
| WithTy of Exp * Type
Sample Code:
let f x = let g x = x
g x
AST instance of Sample Code
[Let
(PApp
(PVar
("f",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 4;
endColumn = 5;};}),
PVar
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 6;
endColumn = 7;};})),
Let
(PApp
(PVar
("g",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 14;
endColumn = 15;};}),
PVar
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 16;
endColumn = 17;};})),
Var
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 20;
endColumn = 21;};}),
App
(Var
("g",
{srcFilename =
"test.fs";
srcLine = {startLine = 2;
endLine = 2;};
srcColumn = {startColumn = 10;
endColumn = 11;};}),
Var
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 2;
endLine = 2;};
srcColumn = {startColumn = 12;
endColumn = 13;};}))),Lit Unit)]
Given the following AST definition and sample code, what would be the best algorithm to find all the usages of an identifier given its position in the tree ?
AST Definition
type Literal
= Char of char // character literal
| String of string // string literal
| Integer of int // integer literal
| Float of float // floating point literal
| Double of double
| Unit
type SrcCol = { startColumn : int; endColumn : int }
type SrcLine = { startLine : int; endLine : int }
type SrcLoc = { srcFilename : string; srcLine : SrcLine; srcColumn : SrcCol }
type Pat =
| PVar of 'a
| PApp of Pat * Pat
| PLit of Literal
| PWithTy of Pat * Type
type Exp
= Var of 'a // variable
| Lam of Pat list * Exp // lambda abstraction
| App of Exp * Exp // application
| Let of Pat * Exp * Exp // local definition
| Lit of Literal // literal
| WithTy of Exp * Type
Sample Code:
let f x = let g x = x
g x
AST instance of Sample Code
[Let
(PApp
(PVar
("f",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 4;
endColumn = 5;};}),
PVar
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 6;
endColumn = 7;};})),
Let
(PApp
(PVar
("g",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 14;
endColumn = 15;};}),
PVar
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 16;
endColumn = 17;};})),
Var
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 1;
endLine = 1;};
srcColumn = {startColumn = 20;
endColumn = 21;};}),
App
(Var
("g",
{srcFilename =
"test.fs";
srcLine = {startLine = 2;
endLine = 2;};
srcColumn = {startColumn = 10;
endColumn = 11;};}),
Var
("x",
{srcFilename =
"test.fs";
srcLine = {startLine = 2;
endLine = 2;};
srcColumn = {startColumn = 12;
endColumn = 13;};}))),Lit Unit)]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上,需要任何类型的带有所需属性过滤器的树节点枚举。深度优先搜索(如另一个答案中提出的)是枚举节点的一种方法。
然而,对于特定树节点中的特定标识符,人们通常想知道它代表什么“声明的实体”?否则,您会找到所有参考文献,但它们针对不同的实体,这通常没有帮助。
这需要为所讨论的应用程序语言构建符号表,然后构建标识符节点和符号表条目之间的映射。简单的枚举器无法解决构建符号表的问题。
Basically any kind of enumeration of the tree nodes with a filter for the desired property is what is needed. A depth-first-search (as proposed in another answer) is one way to enumerate the nodes.
However, what one typically wants to know, for a particular identifier in a particular tree node, is what "declared entity" does it represent? Otherwise you find all the references but they are to different entities and that's generally not helpful.
This requires building symbol tables for the application language in question, and then constructing a map between identifier nodes and symbol table entries. A simple enumerator won't do the trick for building symbol tables.
“创建”身份的节点的子树中的 DFS 怎么样?
What about a DFS in the child trees of the node where the ident is "created" ?
看看我周末破解的实现:
http://fsharprefactor.codeplex.com/
似乎工作 :)
Take a look at the implementation I hacked over the weekend:
http://fsharprefactor.codeplex.com/
Seems to work :)
FSharpRefactor 0.1(预览版)在 Visual Studio Gallery 上发布。
http://visualstudiogallery.msdn.microsoft.com/339cbae9 -911d-4f99-9033-3c3564676f45?SRC=Home
干杯;)
FSharpRefactor 0.1 (Preview version) Release on the Visual Studio Gallery.
http://visualstudiogallery.msdn.microsoft.com/339cbae9-911d-4f99-9033-3c3564676f45?SRC=Home
Cheers ;)