Hive代码分析报告(五): 抽象语法树相关类②

2021SC@SDUSC

目录

ASTNodeOrgin类


ASTNodeOrgin类

上一篇博客中,我们分析到,ASTNode类对象的成员数据中可能包含一个ASTOrigin对象,根据项目源代码中ASTNode中与ASTOrigin有关的注释,可以知道这个类可能是用来指明ASTNode所源自的对象。

下面来分析一下这个类

public class ASTNodeOrigin {

  private final String objectType;

  private final String objectName;

  private final String objectDefinition;

  private final String usageAlias;

  private final ASTNode usageNode;


  public ASTNodeOrigin(String objectType, String objectName,

      String objectDefinition, String usageAlias, ASTNode usageNode) {

    this.objectType = objectType;

    this.objectName = objectName;

    this.objectDefinition = objectDefinition;

    this.usageAlias = usageAlias;

    this.usageNode = usageNode;

  }

  public String getObjectType() {

    return objectType;

  }
  public String getObjectName() {

    return objectName;

  }

  public String getObjectDefinition() {

    return objectDefinition;

  }


  public String getUsageAlias() {

    return usageAlias;

  }


  public ASTNode getUsageNode() {

    return usageNode;

  }

}


// End ASTNodeOrigin.java

可以看到,这个类的结构很简单,主要是成员数据的定义和一些简单的函数,从上到下五个函数的主要功能是:

getObjectType()

返回一个ASTNode产生的对象的类型,例如 视图。

getObjectName()

返回产生ASTNode的对象的名称,例如“v”

getObjectDefinition()

返回一个ASTNode产生的对象的定义。

getUsageAlias()

返回产生ASTNode的对象的别名,例如“v1”

(这可以帮助调试上下文相关的扩展)

getUsageNode()

返回触发对象使用的表达式节点

例如:v as v1(这可以帮助调试上下文相关的扩展)

这里,不免产生一些疑惑,ASTNode的来源是ASTNodeOrigin的,但ASTNodeOrigin并不是ASTNode的父类,这里,ASTNodeOrigin和ASTNode在工作中是什么样的一种关系呢?

其官方介绍中的介绍给到我很大的理解上的帮助。

/**

 * ASTNodeOrigin contains contextual information about the object from whose

 * definition a particular ASTNode originated. For example, suppose a view v is

 * defined as <code>select x+1 as y from t</code>, and we're processing a query

 * <code>select v1.y from v as v1</code>, and there's a type-checking problem

 * with the expression <code>x+1</code> due to an ALTER TABLE on t subsequent to

 * the creation of v. Then, when reporting the error, we want to provide the

 * parser location with respect to the definition of v (rather than with respect

 * to the top-level query, since that represents a completely different

 * "parser coordinate system").

 *

 *<p>

 *

 * So, when expanding the definition of v while analyzing the top-level query,

 * we tag each ASTNode with a reference to an ASTNodeOrign describing v and its

 * usage within the query.

上面这段话大概意思如下

ASTNode可能包含一个ASTNodeOrigin对象,后者包含了该ASTNode来源(由于哪个对象/表的定义,才导致这个ASTNode的出现)信息。

就例如,假设有一个视图v被这样定义:

select x+1 as y from t

在视图定义之后,又通过如下命令

alter table

修改了表t,使得x的类型不再是数值。那么之后,当我们需要处理了如下的命令时:

select v1.y from v as v1

在处理这个query的时候,会进行视图的“展开,然后会发生类型检查错误:比如,x+1”这个表达式类型不合法。我们必须报告错误。问题就在于,我们报告错误时,希望报告视图v定义的地方,而不是发生这个query的地方。因此,在分析query的过程中,对视图v进行展开的时候,我们会为每个展开的ASTNode对象设置一个ASTNodeOrigin对象,这个ASTNodeOrigin对象描述视图v及它在展开它的query中的使用。

综合前文所述,结合分析可知,ASTNodeOrigin主要对ASTNode起到一个辅助作用,ASTNode对象表示一个AST节点。它是对CommonTree的一个简单封装,提供追踪ASTNodeOrigin的功能、并实现Node和Serializable接口。

回顾补充

在了解了AST基本结构和作用后,我又回过头,捋了一遍整个流程。

前面的语法分析、词法分析中, Hive.g文件中定义了一些逻辑Token(即所谓的imaginary token)。这些token都以TOK_开头。这些token一般作为AST中的节点出现,用于表示以这个节点为根节点的子树的逻辑语义

例如:

•^(TOK_SELECT hintClause? SelectList)

表示一棵Select子树(语义),它的根是TOK_SELECT,它的两个分支分别是hintClause和selectList产生的子树。

•^(TOK_SELECT ^(TOK_SELEXPR trfmClause))

也是一棵Select子树(语义),它的根同样也是TOK_SELECT,它只有一个分支,就是以TOK_SELEXPR为根的select表达式子树。

另外,Hive.g中为HiveParser定义了一个Stack msgs成员,这个成员主要用处是报告错误。在每条parser规则应用之前向msgs中压栈这条规则的名字,在应用之后msgs弹栈。这样,在出现错误的时候,栈顶就是正在被应用的parser规则,栈中则包含了parser规则应用的完整路径。

之后,在生成了HiveLexer和HiveParser类之后,ParseDriver负责组织、驱动整个词法、语法分析流程,并得到分析后的AST。

其中,在使用生成的Parser的时候,会给它设置该适配器对象。Parser每当需要使用某个token创建一个AST节点的时候,会调用该对象的create(token)进行创建。这里,适配器对象会创建一个ASTNode并返回。

这样,整个语法分析、词法分析、AST的生成,我们就有了一个整体的了解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值