语法分析器根据语法将标记流(来自词法分析器)转换为语法树。

任务描述

从“词法分析器” 中获取输出,并根据以下语法将其转换为抽象语法树(AST)。输出应为扁平格式。

程序应从文件和/或stdin读取输入,并将输出写入文件和/或stdout。如果使用的语言具有解析器模块/库/类,则提供两种版本的解决方案将是很好的选择:一个不带解析器模块,另一个带解析器模块。

语法

    stmt_list           =   {stmt} ;stmt                =   ';'| Identifier '=' expr ';'| 'while' paren_expr stmt| 'if' paren_expr stmt ['else' stmt]| 'print' '(' prt_list ')' ';'| 'putc' paren_expr ';'| '{' stmt_list '}';paren_expr          =   '(' expr ')' ;prt_list            =   (string | expr) {',' (String | expr)} ;expr                =   and_expr            {'||' and_expr} ;and_expr            =   equality_expr       {'&&' equality_expr} ;equality_expr       =   relational_expr     [('==' | '!=') relational_expr] ;relational_expr     =   addition_expr       [('<' | '<=' | '>' | '>=') addition_expr] ;addition_expr       =   multiplication_expr {('+' | '-') multiplication_expr} ;multiplication_expr =   primary             {('*' | '/' | '%') primary } ;primary             =   Identifier| Integer| '(' expr ')'| ('+' | '-' | '!') primary

得到的AST应该表示为二叉树。
示例
给定一个简单程序(如下),该程序存储在一个名为while.t的文件中,使用一种词法分析器创建标记列表。

lex < while.t > while.lex

运行一种语法分析器

parse < while.lex > while.ast

while.t

count = 1;while (count < 10) {print("count is: ", count, "\n");count = count + 1;}

while.lex

    1      1 Identifier      count1      7 Op_assign1      9 Integer             11     10 Semicolon2      1 Keyword_while2      7 LeftParen2      8 Identifier      count2     14 Op_less2     16 Integer            102     18 RightParen2     20 LeftBrace3      5 Keyword_print3     10 LeftParen3     11 String          "count is: "3     23 Comma3     25 Identifier      count3     30 Comma3     32 String          "\n"3     36 RightParen3     37 Semicolon4      5 Identifier      count4     11 Op_assign4     13 Identifier      count4     19 Op_add4     21 Integer             14     22 Semicolon5      1 RightBrace6      1 End_of_input

while.ast

Sequence
Sequence
;
Assign
Identifier    count
Integer       1
While
Less
Identifier    count
Integer       10
Sequence
Sequence
;
Sequence
Sequence
Sequence
;
Prts
String        "count is: "
;
Prti
Identifier    count
;
Prts
String        "\n"
;
Assign
Identifier    count
Add
Identifier    count
Integer       1

详细说明
节点类型名称列表

Identifier String Integer Sequence If Prtc Prts Prti While Assign Negate Not Multiply Divide Mod
Add Subtract Less LessEqual Greater GreaterEqual Equal NotEqual And Or

在下文中,Null/Empty节点代表";"。

非根(内部)节点
对于操作符,应该创建以下节点:

Multiply Divide Mod Add Subtract Less LessEqual Greater GreaterEqual Equal NotEqual And Or

对于上面的每个节点,左子节点和右子节点是各自操作的操作数。
采用伪S-Expression格式:

(Operator expression expression)

Negate, Not
对于这些节点类型,左节点是操作数,右节点为空。

(Operator expression ;)

Sequence - 子节点是statement或Sequence。
If - 左节点是expression,右节点是if节点, 同时它的左节点是if-true语块右节点是if-false (else) 语块。

(If expression (If statement else-statement))

如果没有else, 这棵树变成:

(If expression (If statement ;))

Prtc

(Prtc (expression) ;)

Prts

(Prts (String "the string") ;)

Prti

(Prti (Integer 12345) ;)

While - 左节点是expression,右节点是statement.

(While expression statement)

Assign - 左节点是赋值的左边,右节点是赋值的右边。

(Assign Identifier expression)

终端(叶子)节点:

Identifier: (Identifier ident_name)
Integer:    (Integer 12345)
String:     (String "Hello World!")
";":        Empty node

举例
实现以下程序:

   a=11;

用二叉树来实现以下AST:
每个非叶子节点下有两个’|'行。第一个表示左子节点,第二个表示右子节点

   (1) Sequence(2)     |-- ;(3)     |-- Assign(4)         |-- Identifier: a(5)         |-- Integer: 11

扁平化形式:

   (1) Sequence(2) ;(3) Assign(4) Identifier    a(5) Integer       11

实现以下程序:

   a=11;b=22;c=33;

生成AST:

   ( 1) Sequence( 2)     |-- Sequence( 3)     |   |-- Sequence( 4)     |   |   |-- ;( 5)     |   |   |-- Assign( 6)     |   |       |-- Identifier: a( 7)     |   |       |-- Integer: 11( 8)     |   |-- Assign( 9)     |       |-- Identifier: b(10)     |       |-- Integer: 22(11)     |-- Assign(12)         |-- Identifier: c(13)         |-- Integer: 33

扁平化形式:

   ( 1) Sequence( 2) Sequence( 3) Sequence( 4) ;( 5) Assign( 6) Identifier    a( 7) Integer       11( 8) Assign( 9) Identifier    b(10) Integer       22(11) Assign(12) Identifier    c(13) Integer       33

解析器的伪代码
使用优先级上升进行表达式解析,并使用递归下降进行语句解析

def expr(p)if tok is "("x = paren_expr()elif tok in ["-", "+", "!"]gettok()y = expr(precedence of operator)if operator was "+"x = yelsex = make_node(operator, y)elif tok is an Identifierx = make_leaf(Identifier, variable name)gettok()elif tok is an Integer constantx = make_leaf(Integer, integer value)gettok()elseerror()while tok is a binary operator and precedence of tok >= psave_tok = tokgettok()q = precedence of save_tokif save_tok is not right associativeq += 1x = make_node(Operator save_tok represents, x, expr(q))return xdef paren_expr()expect("(")x = expr(0)expect(")")return xdef stmt()t = NULLif accept("if")e = paren_expr()s = stmt()t = make_node(If, e, make_node(If, s, accept("else") ? stmt() : NULL))elif accept("putc")t = make_node(Prtc, paren_expr())expect(";")elif accept("print")expect("(")repeatif tok is a stringe = make_node(Prts, make_leaf(String, the string))gettok()elsee = make_node(Prti, expr(0))t = make_node(Sequence, t, e)until not accept(",")expect(")")expect(";")elif tok is ";"gettok()elif tok is an Identifierv = make_leaf(Identifier, variable name)gettok()expect("=")t = make_node(Assign, v, expr(0))expect(";")elif accept("while")e = paren_expr()t = make_node(While, e, stmt()elif accept("{")while tok not equal "}" and tok not equal end-of-filet = make_node(Sequence, t, stmt())expect("}")elif tok is end-of-filepasselseerror()return tdef parse()t = NULLgettok()repeatt = make_node(Sequence, t, stmt())until tok is end-of-filereturn t

一旦构建了AST,就应该以扁平格式输出它。这可以像下面这样

def prt_ast(t)if t == NULLprint(";\n")elseprint(t.node_type)if t.node_type in [Identifier, Integer, String]     # leaf nodeprint the value of the Ident, Integer or String, "\n"elseprint("\n")prt_ast(t.left)prt_ast(t.right)

如果正确地构建了AST,那么将它用以下操作加载到后续程序

def load_ast()line = readline()# Each line has at least one tokenline_list = tokenize the line, respecting double quotestext = line_list[0] # first token is always the node typeif text == ";"   # a terminal nodereturn NULLnode_type = text # could convert to internal form if desired# A line with two tokens is a leaf node# Leaf nodes are: Identifier, Integer, String# The 2nd token is the valueif len(line_list) > 1return make_leaf(node_type, line_list[1])left = load_ast()right = load_ast()return make_node(node_type, left, right)

最后,还可以通过对AST解释器解决方案之一运行AST来测试它。
假设它测试程序一个名为prime.t的文件中
lex <prime.t | parse
输入到词法分析器的代码:

/*Simple prime number generator*/
count = 1;
n = 1;
limit = 100;
while (n < limit) {k=3;p=1;n=n+2;while ((k*k<=n) && (p)) {p=n/k*k!=n;k=k+2;}if (p) {print(n, " is prime\n");count = count + 1;}
}
print("Total primes found: ", count, "\n");

从词法分析器输出,并输入到语法分析器:

    4      1 Identifier      count4      7 Op_assign4      9 Integer             14     10 Semicolon5      1 Identifier      n5      3 Op_assign5      5 Integer             15      6 Semicolon6      1 Identifier      limit6      7 Op_assign6      9 Integer           1006     12 Semicolon7      1 Keyword_while7      7 LeftParen7      8 Identifier      n7     10 Op_less7     12 Identifier      limit7     17 RightParen7     19 LeftBrace8      5 Identifier      k8      6 Op_assign8      7 Integer             38      8 Semicolon9      5 Identifier      p9      6 Op_assign9      7 Integer             19      8 Semicolon10      5 Identifier      n10      6 Op_assign10      7 Identifier      n10      8 Op_add10      9 Integer             210     10 Semicolon11      5 Keyword_while11     11 LeftParen11     12 LeftParen11     13 Identifier      k11     14 Op_multiply11     15 Identifier      k11     16 Op_lessequal11     18 Identifier      n11     19 RightParen11     21 Op_and11     24 LeftParen11     25 Identifier      p11     26 RightParen11     27 RightParen11     29 LeftBrace12      9 Identifier      p12     10 Op_assign12     11 Identifier      n12     12 Op_divide12     13 Identifier      k12     14 Op_multiply12     15 Identifier      k12     16 Op_notequal12     18 Identifier      n12     19 Semicolon13      9 Identifier      k13     10 Op_assign13     11 Identifier      k13     12 Op_add13     13 Integer             213     14 Semicolon14      5 RightBrace15      5 Keyword_if15      8 LeftParen15      9 Identifier      p15     10 RightParen15     12 LeftBrace16      9 Keyword_print16     14 LeftParen16     15 Identifier      n16     16 Comma16     18 String          " is prime\n"16     31 RightParen16     32 Semicolon17      9 Identifier      count17     15 Op_assign17     17 Identifier      count17     23 Op_add17     25 Integer             117     26 Semicolon18      5 RightBrace19      1 RightBrace20      1 Keyword_print20      6 LeftParen20      7 String          "Total primes found: "20     29 Comma20     31 Identifier      count20     36 Comma20     38 String          "\n"20     42 RightParen20     43 Semicolon21      1 End_of_input

语法分析器的输出:

Sequence
Sequence
Sequence
Sequence
Sequence
;
Assign
Identifier    count
Integer       1
Assign
Identifier    n
Integer       1
Assign
Identifier    limit
Integer       100
While
Less
Identifier    n
Identifier    limit
Sequence
Sequence
Sequence
Sequence
Sequence
;
Assign
Identifier    k
Integer       3
Assign
Identifier    p
Integer       1
Assign
Identifier    n
Add
Identifier    n
Integer       2
While
And
LessEqual
Multiply
Identifier    k
Identifier    k
Identifier    n
Identifier    p
Sequence
Sequence
;
Assign
Identifier    p
NotEqual
Multiply
Divide
Identifier    n
Identifier    k
Identifier    k
Identifier    n
Assign
Identifier    k
Add
Identifier    k
Integer       2
If
Identifier    p
If
Sequence
Sequence
;
Sequence
Sequence
;
Prti
Identifier    n
;
Prts
String        " is prime\n"
;
Assign
Identifier    count
Add
Identifier    count
Integer       1
;
Sequence
Sequence
Sequence
;
Prts
String        "Total primes found: "
;
Prti
Identifier    count
;
Prts
String        "\n"
;

代码实现

C实现
Go实现
Java实现
JavaScript实现
Python实现

编译器之语法分析器(syntax analyzer)相关推荐

  1. 编译原理——语法分析器(SLR)

    编译原理--语法分析器(SLR) 识别语法结构: 变量声明(不含变量初始化) if单条件分支语句以及if else 双条件分支语句 for循环和while循环语句 赋值语句 ,四则运算,逻辑判断复合语 ...

  2. 编译原理-语法分析器设计

    文章目录 语法分析器设计 实验环境 实验目的 实验内容及要求 实验步骤 用上下文无关文法表达 改写为LL(1)文法 First集与Follow集 预测分析表 结果分析 源代码 语法分析器设计 实验环境 ...

  3. 编译原理—语法分析器(Java)

    递归下降语法分析 1. 语法成分说明 <语句块> ::= begin<语句串> end <语句串> ::= <语句>{:<语句>} < ...

  4. 编译原理------语法分析器C/C++代码实现

    一.实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. 二.实验内容 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. 2.1 待分析的简单语言的语 ...

  5. 编译原理语法分析器实验报告

    编号: 实习 一 二 三 四 五 六 七 八 九 十 总评 教师签名 成绩 第一部分 语言语法规则 Mini语言包含程序设计所需要的最基本语言成分,包括 程序定义语句 :以 program 开头 en ...

  6. 编译原理——语法分析器(C/C++代码实现)

    0

  7. 《编译原理》实验报告——基于YACC的TINY语法分析器的构建

    一.实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验方案 (1)设计基于LEX的TINY词法分析器 (2)设计基于YACC的TINY语法分析器 ( ...

  8. 编译原理——实验叁——基于YACC的TINY语法分析器的构建

    一. 实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二. 实验方案 (1)设计基于YACC的TINY词法分析器 (2)设计基于LEX的TINY语法分析器 ...

  9. 编译原理——实验叁预习报告——基于YACC的TINY语法分析器的构建

    一.实验目的: 运用YACC,针对给定的文法,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验预习提示 1.表达:针对5.5节中的calculator文法,设计输入和输出 2.观察:观察p ...

最新文章

  1. 服务器端会话技术Session|| Session的原理||Session的细节||session的钝化session的活化||session的特点||session与Cookie的区别
  2. python map reduce filter_Python map, reduce, filter和sorted
  3. android小闹钟程序,Android实现闹钟小程序.pdf
  4. .NET 6新特性试用 | 无需配置开发人员异常页
  5. python根据列表绘制柱状图_python把一个列表画柱状图
  6. Linux内核的裁剪和移植
  7. 如何参与一个GitHub开源项目
  8. cmake linux模板 多目录_多目录工程的CmakeLists.txt编写(自动添加多目录下的文件)...
  9. oracle的sga怎么设置,oracle sga设置
  10. txt替换回车键符号怎么打_电脑键盘上那个点符号怎么打出来的?
  11. Mail.Ru Cup 2018 Round 1 virtual participate记
  12. 如何在数据源是空的时候,gridview显示表头(万能)
  13. Zend Framework学习之常用校验器
  14. CRC32的C语言源代码
  15. Wireshark 在MacOS10.15.3 系统无法显示网卡的解决方法
  16. java u0000_Java-从字符串中删除\ u0000
  17. iOS开发:获取WiFi名称(解决iOS12.0以上系统不能正常获取WiFi名称的方法)
  18. java毕业设计在线音乐系统Mybatis+系统+数据库+调试部署
  19. mysql中日期相减_Excel日期和时间运算
  20. 内存优化(一)浅谈内存优化

热门文章

  1. 进程管理 进程的调度
  2. Stream流练习题大全以及答案
  3. c语言 读取TXT 去空格,C语言读取TXT文件,忽略文件空格,把内容写入数组中应该如何实现...
  4. php正则匹配是否为url地址,php正则匹配网址-正则php-php正则匹配url地址
  5. 行人重识别(Person re-identification)概述
  6. eclipse 项目中搜索资源(类方法,文件名,文件中的字符串)
  7. MyCat启动报错,运行./mycat console报错 Unrecognized VM option 'AggressiveOpts'
  8. Windows CreateFont:创建自己的字体
  9. vsync与hsync
  10. java下载zip文件损坏_使用Java下载.zip文件会导致损坏的.zip文件?