任务分散相比于语法分析 两个重要任务

  1. 类型检查 (Type Checking):javascript类型系统奇怪,数字和字符串相加1 4+‘7’ or2 4*‘7’.类型系统,分类 两个维度 强cpp java 弱 ; 动态与静态 什么时候做类型检查。类型 很大的话题。《Type Theory》函数式语言 haskell coq 待查
  2. 符号检查 symbols符号:变量名、函数名、类型名、标签名(goto),……

[! example] 6 two 未定义先使用 7 同样的错误 9 把变量当函数用 10 重复定义


符号表的位置

定义 概念

那么首先要把符号都收集起来。

定义:符号表,一个数据结构,保存各种符号相关信息。

设计实现的难点 作用域

DSL:领域特定语言 通常只有单作用域(全局) GPL: 通用程序设计语言 通常需要嵌套作用域 ,嵌套哈希表 多个符号表构成的树状结构 有些是分开的

Example

左边程序对应右边的符号表 三类作用域:

  • 根节点:全局作用域,全局变量和函数名
  • 局部作用域:左右花括号,当我看到左括号开始,一种情况跟着函数 3-6;实际上任意一对花括号可 4 ;
  • 函数作用域:错误的 它认为 函数形参构成了一个单独作用域,实际语言中是与花括号一起的。但是今天讲的是分开。

实现 scope

  • 一个重要属性 外部作用域 即父节点。为什么需要?该符号定义可能不在当前作用域。

define

放到符号表里

public void define(Symbol symbol){
	this.symbols.put(symbol.getName(),symbol);
	System.out.println("+"+symbol);
}

resolve

解析 树结构 顺着指针向上找

public Symbol resolve(string name){
Symbol symbol = this.symbols.get(name);
if(symbol != null){
	System.out.println("-"+name);
	return symbol
}
 
//递归
//先看父节点是否为空,根节点,全局作用域
if(this.enclosingScope != null){
 
	return this.enclosingScope.resolve(name);
}
//报错
System.out.println("?"+name);
return null;
}
  • 清楚需要做的任务

在构建语法分析树中 构建作用域树

两个变量,1 根节点 全局作用域 2 current scope,每当创建一个作用域或者当前作用域退出的时候指向它的父作用域

4 个任务

  1. create and enter a new scope 识别在什么时机创建并进入 三类作用域的开始和进入 全局 局部 画树状图记得 加上父子关系的边,做三件事情 函数 特殊 也是符号 还要解析 返回类型

  2. define symbols 解析类型 拿到变量的名字 构建一个变量相对应的符号 把这个符号放到符号表里

  3. use symbols 变量和函数的使用

  4. exit the current scope and return to its enclosing scope 也是对应三种 为了展示 添加了 第一行

struct/class 类型作用域

d.i=a.b.y解析i的时候 明确是到哪里解析。

weird javascript again

Footnotes

  1. 47

  2. 28