词法分析原理
学习课程- 华南理工大学- 刘欣欣
参考教程
参考学习的课程
js 版本的课程
计算机编译的过程
- 词法分析
- 语法分析
- 中间代码生成
- 优化
- 目标代码产生
词法分析单元
=> <token-name, attr-value>
词法分析课程
- 词法分析器的设计
- 正规表达式与有限自动机
- 词法分析器的自动生成 –LEX
单词符号的识别
-
超前搜索
- 基本字识别
- 标识符识别:
- 字母开头的字母数字串,后跟界符或算符
-
几点限制 – 不必使用超前搜索
- 所有基本字都是保留字,用户不能用它们作为自己的标识符
- 基本字作为特殊的标识符来处理,使用保留表
-
状态转化图
- 状态转化图是个有限方向图
- 用于识别或者接受一定的字符串
参考的项目 antlr
词法分析器的设计
基本概念:
-
确定有限自动机(Deterministic Finite Automaton) 简称DFA。dfa是匹配速度,是确定的。
-
非确定有限自动机(Nondeterministic Finite Automaton) 简称NFA,nfa是匹配结果,是不确定的。
-
DFA比较快,但不提供Backtrack(回溯)功能,NFA比较慢,但提供了Backtrack功能。
-
NFA是基于表达式的(Regex-Directed),而DFA是基于文本的(Text-Directed)。
-
DFA引擎在任意时刻必定处于某个确定的状态,而NFA引擎可能处于一组状态之中的任何一个,所以,NFA引擎必须记录所有的可能路径(trace multiple possible routes through the NFA),NFA之所以能够提供Backtrack的功能,原因就在这里。
NFA 和 DFA 是等价的, NFA 可以转化为 DFA
参考的开源项目
开源项目参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
import (
"fmt"
)
// 定义状态变量
const (
Initial = iota // 初始状态
ID // 原始状态
Num
GT
GE
)
func isNum(c rune) bool {
if c >= '0' && c <= '9' {
return true
}
return false
}
func isAlpha(c rune) bool {
if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') {
return true
}
return false
}
func main() {
// 读取输入的文本
_srcRawLine := "age12>=45" + "\n"
var _state = Initial
var _outToken = ""
for _, _char := range _srcRawLine {
var _doTwice = false
for {
switch _state {
case Initial:
_doTwice = true
_outToken = ""
if isNum(_char) {
_state = Num
} else if isAlpha(_char) {
_state = ID
} else if _char == '>' {
_state = GT
}
_outToken += string(_char)
//break
case ID:
if isAlpha(_char) || isNum(_char) || _char == '_' {
_outToken += string(_char)
} else {
fmt.Println("ID", _outToken)
_state = Initial
}
//break
case Num:
if isNum(_char) {
_outToken += string(_char)
} else {
fmt.Println("Num", _outToken)
_state = Initial
}
//break
case GT:
if _char == '=' {
_outToken += string(_char)
_state = GE
} else {
fmt.Println("OP", _outToken)
_state = Initial
}
//break
case GE:
fmt.Println("OP", _outToken)
_state = Initial
//break
}
if _state != Initial || _doTwice {
break
}
}
}
//结束时输出
// switch _state {
// case ID:
// fmt.Println("ID", _outToken)
// break
// case Num:
// fmt.Println("Num", _outToken)
// break
// case GT:
// fmt.Println("OP", _outToken)
// break
// case GE:
// fmt.Println("OP", _outToken)
// break
// }
}
|
NFA 是不确定的, DFA 是确定的,因此 要将不确定的 NFA 转化为 DFA 这种才好。
学习教程
参考b站教程