如何在 AST 中查找标识符的用法?

发布于 2024-10-06 20:25:06 字数 3860 浏览 5 评论 0原文

给定以下 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如此安好 2024-10-13 20:25:06

基本上,需要任何类型的带有所需属性过滤器的树节点枚举。深度优先搜索(如另一个答案中提出的)是枚举节点的一种方法。

然而,对于特定树节点中的特定标识符,人们通常想知道它代表什么“声明的实体”?否则,您会找到所有参考文献,但它们针对不同的实体,这通常没有帮助。

这需要为所讨论的应用程序语言构建符号表,然后构建标识符节点和符号表条目之间的映射。简单的枚举器无法解决构建符号表的问题。

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.

祁梦 2024-10-13 20:25:06

“创建”身份的节点的子树中的 DFS 怎么样?

What about a DFS in the child trees of the node where the ident is "created" ?

凉城凉梦凉人心 2024-10-13 20:25:06

看看我周末破解的实现:

http://fsharprefactor.codeplex.com/

似乎工作 :)

Take a look at the implementation I hacked over the weekend:

http://fsharprefactor.codeplex.com/

Seems to work :)

烦人精 2024-10-13 20:25:06

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 ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文