0%

编译原理-自定义Hua语言

阅读更多

1 基本概念

1.1 文法符号

在文法定义中会有两种类型的符号:一种称为终结符,另一种称为非终结符

所谓终结符就是不可再分的符号,是原子的,是具体的语法成分。例如,在英文文法中,每个字母就是终结符,标点符号就是终结符。又例如,在Java文法中,所有关键字(int、boolean、void、abstract、public、return等等),分号,逗号、括号都属于终结符

所谓非终结符就是可以再分的符号,是非原子的,是抽象的语法成分。例如,在英文文法中,单词,祈使句、宾语从句、状语从句就是非终结符。又例如,在Java文法中,if语句、while语句,方法定义、类定义、赋值语句等等都属于非终结符

为了方便描述,我们有如下约定

  1. 排在前面的大写字母表示非终结符,例如$A$、$B$、$C$、$D$、$E$、$F$、$G$
  2. $S$表示文法开始符号
  3. 排在前面的小写字母表示终结符,例如$a$、$b$、$c$
  4. $w$表示终结符号串
  5. 排在后面的大写字母表示文法符号,例如$X$、$Y$、$Z$
  6. $α$、$β$等希腊字母表示文法符号串

1.2 文法符号串

文法符号串由文法符号组合而成,文法符号包括终结符和非终结符。当然单个的文法符号也属于文法符号串

1.3 产生式

产生式描述了不同文法符号串之间的转换关系,这种关系是单向的。例如

$$\alpha \to \beta$$

1.4 文法

文法由一系列产生式构成,根据产生式形式的不同,我们将文法分为四种类型

  • 0-型文法,又称为无限制文法$$\alpha \to \beta$$
  • 1-型文法,又称为上下文有关文法$$\alpha_1A\alpha_2 \to \alpha_1\beta\alpha_2,|\alpha|≤|\beta|$$
  • 2-型文法,又称为上下文无关文法$$A \to \beta$$
  • 3-型文法,又称为正则文法$$A \to wB\;\;\;or\;\;\;A \to w$$ or $$A \to Bw\;\;\;or\;\;\;A \to w$$

一般的编程语言都是2-型文法,即上下文无关文法

1.5 分析法概述

这里,我们只讨论上下文无关文法(3-型文法)

一般而言,分析法有$LL(n)$和$LR(n)$分析两种,其中

  1. $LL(n)$:第一个$L$表示从左到右扫描输入串,第二个$L$表示最左推导,$n$表示向后看几个输入符号,通常只有1才有实践意义
  2. $LR(n)$:第一个$L$表示从左到右扫描输入串,第二个$R$表示最右规约,$n$表示向后看几个输入符号,通常取0和1才有实践意义

对于$LL(n)$分析法,语法分析过程可以概括为以下几个步骤

  1. 计算first集合
  2. 计算follow集合
  3. 计算select集合
  4. 生成预测分析表

对于$LR(n)$分析法,预发分析过程可以概括为以下几个步骤

  1. 计算first集合
  2. 计算follow集合
  3. 生成LR自动机
  4. 生成预测分析表

1.5.1 first集

$First(X)$定义为可以由文法符号$X$推导出的所有终结符集合
  • 显然如果$X$是终结符,那么$First(X)=\{X\}$

1.5.2 follow集

$First(A)$定义为可以紧跟在非终结符$A$之后的所有终结符集合,不包括$\epsilon$

2 正则表达式实践篇

正则表达式引擎

  • base package: org.liuyehcf.grammar.rg
  • 包括nfa自动机以及dfa自动机
  • 支持以下正则表达式通配符: .?*+|
  • 支持量词{}
  • 支持部分转义,包括\d\D\w\W\s\S
  • 支持[]
  • nfa自动机支持捕获组(nfa转dfa时,捕获组信息会丢失,因此dfa自动机尚不支持捕获组。目前还没有很好的解决方法)

3 编译引擎介绍

我们来回顾一下编译过程

  1. 词法分析
  2. 语法分析
  3. 语义分析
  4. 中间代码生成
  5. 代码优化
  6. 存储管理

由于词法分析、语法分析过程对于任何语言来说都是相同的,而语义分析是针对特定语言的,是无法泛化的。因此,我设计的编译引擎将词法分析语法分析语义分析及后续进行了解耦,语法分析的过程交给编译引擎来完成。在设计Hua语言时,只需要关注语义分析即可

4 Hua语言实践篇

4.1 文法定义

Hua文法的定义参考了Java的文法定义,且大部分保持一致。包含如下主要的语法成分

  1. 支持方法定义、方法重载、方法调用
  2. 支持变量定义
  3. 支持基本类型int和boolean
  4. 支持数组类型、多维数组
  5. 支持基本的控制流语句,包括
    • if then
    • if then else
    • while
    • do while
    • for
    • condition expression
  6. 支持二元运算符
    • *
    • /
    • %
    • +
    • -
    • <<
    • >>
    • >>>
    • &
    • ^
    • |
    • ||
    • &&
  7. 支持一些系统函数,目前仅包含
    • print(int)
    • print(boolean)
    • nextInt(int,int)
    • nextInt()
    • nextBoolean()

以下就是HUA语言的文法定义

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
108
109
110
111
<additive expression> → <additive expression> + <multiplicative expression> | <additive expression> - <multiplicative expression> | <multiplicative expression>
<and expression> → <and expression> & <equality expression> | <equality expression>
<argument list> → <argument list> , <expression> | <expression>
<array access> → <expression name> <mark 286_1_1> [ <expression> ] | <primary no new array> [ <expression> ]
<array creation expression> → new <primitive type> <dim exprs> <epsilon or dims>
<array type> → <type> [ ]
<assignment expression> → <assignment> | <conditional expression>
<assignment operator> → %= | &= | *= | += | -= | /= | <<= | = | >>= | >>>= | ^= | |=
<assignment> → <left hand side> <assignment operator> <mark 222_1_1> <assignment expression>
<block statement> → <local variable declaration statement> | <statement>
<block statements> → <block statement> | <block statements> <block statement>
<block> → { <mark 139_1_1> <epsilon or block statements> }
<boolean literal> → false | true
<cast expression> → ( <primitive type> ) <unary expression> | ( <reference type> ) <unary expression not plus minus>
<conditional and expression> → <conditional and expression> && <mark 232_2_1> <inclusive or expression> | <inclusive or expression>
<conditional expression> → <conditional or expression> | <conditional or expression> ? <mark true block> <expression> : <mark false block> <conditional expression>
<conditional or expression> → <conditional and expression> | <conditional or expression> || <mark 230_2_1> <conditional and expression>
<decimal integer literal> → <decimal numeral>
<decimal numeral> → 0 | <non zero digit> <epsilon or digits>
<digit> → 0 | <non zero digit>
<digits> → <digit> | <digits> <digit>
<dim expr> → [ <expression> ]
<dim exprs> → <dim expr> | <dim exprs> <dim expr>
<dims> → [ ] | <dims> [ ]
<do statement> → do <mark loop offset> <statement> while ( <expression> ) ;
<empty statement> → ;
<epsilon or argument list> → __ε__ | <argument list>
<epsilon or block statements> → __ε__ | <block statements>
<epsilon or digits> → __ε__ | <digits>
<epsilon or dims> → __ε__ | <dims>
<epsilon or expression> → __ε__ | <expression>
<epsilon or for init> → __ε__ | <for init>
<epsilon or for update> → __ε__ | <for update>
<epsilon or formal parameter list> → __ε__ | <formal parameter list>
<equality expression> → <equality expression> != <relational expression> | <equality expression> == <relational expression> | <relational expression>
<exclusive or expression> → <and expression> | <exclusive or expression> ^ <and expression>
<expression name> → @identifier
<expression statement> → <statement expression> ;
<expression> → <assignment expression>
<floating-point type> → float
<for init> → <local variable declaration> | <statement expression list>
<for statement no short if> → for ( <mark before init> <epsilon or for init> ; <mark loop offset> <epsilon or expression> ; <mark before update> <epsilon or for update> ) <mark after update> <statement no short if>
<for statement> → for ( <mark before init> <epsilon or for init> ; <mark loop offset> <epsilon or expression> ; <mark before update> <epsilon or for update> ) <mark after update> <statement>
<for update> → <statement expression list>
<formal parameter list> → <formal parameter list> , <formal parameter> | <formal parameter>
<formal parameter> → <type> <mark 50_1_1> <variable declarator id>
<if then else statement no short if> → if ( <expression> ) <mark true block> <statement no short if> else <mark false block> <statement no short if>
<if then else statement> → if ( <expression> ) <mark true block> <statement no short if> else <mark false block> <statement>
<if then statement> → if ( <expression> ) <mark true block> <statement>
<inclusive or expression> → <exclusive or expression> | <inclusive or expression> | <exclusive or expression>
<integer literal> → <decimal integer literal>
<integral type> → int
<left hand side> → <array access> | <expression name>
<literal> → <boolean literal> | <integer literal>
<local variable declaration statement> → <local variable declaration> ;
<local variable declaration> → <type> <mark 146_1_1> <variable declarators>
<mark 139_1_1> → __ε__
<mark 146_1_1> → __ε__
<mark 222_1_1> → __ε__
<mark 230_2_1> → __ε__
<mark 232_2_1> → __ε__
<mark 286_1_1> → __ε__
<mark 50_1_1> → __ε__
<mark 66_2_1> → __ε__
<mark 74_1_1> → __ε__
<mark 74_1_2> → __ε__
<mark after update> → __ε__
<mark before init> → __ε__
<mark before update> → __ε__
<mark false block> → __ε__
<mark loop offset> → __ε__
<mark prefix expression> → __ε__
<mark true block> → __ε__
<method body> → ; | <block>
<method declaration> → <mark 74_1_1> <method header> <mark 74_1_2> <method body>
<method declarations> → <method declaration> | <method declarations> <method declaration>
<method declarator> → @identifier ( <epsilon or formal parameter list> )
<method header> → <result type> <method declarator>
<method invocation> → <method name> ( <epsilon or argument list> )
<method name> → @identifier
<multiplicative expression> → <multiplicative expression> % <unary expression> | <multiplicative expression> * <unary expression> | <multiplicative expression> / <unary expression> | <unary expression>
<non zero digit> → @nonZeroDigit
<numeric type> → <floating-point type> | <integral type>
<postdecrement expression> → <postfix expression> --
<postfix expression> → <expression name> | <postdecrement expression> | <postincrement expression> | <primary>
<postincrement expression> → <postfix expression> ++
<predecrement expression> → -- <mark prefix expression> <unary expression>
<preincrement expression> → ++ <mark prefix expression> <unary expression>
<primary no new array> → ( <expression> ) | <array access> | <literal> | <method invocation>
<primary> → <array creation expression> | <primary no new array>
<primitive type> → boolean | <numeric type>
<programs> → <method declarations>
<reference type> → <array type>
<relational expression> → <relational expression> < <shift expression> | <relational expression> <= <shift expression> | <relational expression> > <shift expression> | <relational expression> >= <shift expression> | <shift expression>
<result type> → void | <type>
<return statement> → return <epsilon or expression> ;
<shift expression> → <additive expression> | <shift expression> << <additive expression> | <shift expression> >> <additive expression> | <shift expression> >>> <additive expression>
<statement expression list> → <statement expression list> , <statement expression> | <statement expression>
<statement expression> → <assignment> | <method invocation> | <postdecrement expression> | <postincrement expression> | <predecrement expression> | <preincrement expression>
<statement no short if> → <for statement no short if> | <if then else statement no short if> | <statement without trailing substatement> | <while statement no short if>
<statement without trailing substatement> → <block> | <do statement> | <empty statement> | <expression statement> | <return statement>
<statement> → <for statement> | <if then else statement> | <if then statement> | <statement without trailing substatement> | <while statement>
<type> → <primitive type> | <reference type>
<unary expression not plus minus> → ! <unary expression> | ~ <unary expression> | <cast expression> | <postfix expression>
<unary expression> → + <unary expression> | - <unary expression> | <predecrement expression> | <preincrement expression> | <unary expression not plus minus>
<variable declarator id> → @identifier | <variable declarator id> [ ]
<variable declarator> → <variable declarator id> | <variable declarator id> = <variable initializer>
<variable declarators> → <variable declarator> | <variable declarators> , <mark 66_2_1> <variable declarator>
<variable initializer> → <expression>
<while statement no short if> → while ( <mark loop offset> <expression> ) <mark true block> <statement no short if>
<while statement> → while ( <mark loop offset> <expression> ) <mark true block> <statement>