语法分析原理 - Parsing

简介

Parsing方法分类:
  Universal: Cocke-Younger-Kasami Algorithm and Earley‘s Algorithm.
  Top-down: LL(k).
  Bottom-up: LR(k).

错误恢复模式:
  Panic-Mode Recovery: 
  Phrase-Level Recovery:
  Error Production:
  Global Correction:

上下文无关文法:
  终结符(terminal):组成串的基本符号。
  非终结符(nonterminal):表示串的集合的语法变量,给出了语法分析和翻译的关键。
  开始符号(start symbol):在一个文法中,一个nonterminal被指定为开始符号。
  产生式(production):一条语法产生式,包含一个head/left side,转换符号->/::=,和body/right side。

推导过程:
  最左推导(leftmost derivation):总选择每个句型的最左非终结符号展开。
  最右推导(rightmost derivation):总选择每个句型的最右非终结符号展开,有时也被称为规范推导(canonical derivation)。

算法1:消除左递归

消除立即左递归:
  对于 A -> Aα1 | Aα2 | ... | Aαm | β1 | β2 | ... | βn,将这些A产生式替换为:
  A -> β1A‘ | β2A‘ | ... | βnA‘
  A‘ -> α1A‘ | α2A‘ | ... | αmA‘ | ε

消除循环左递归:
  输入:没有环(A->A)或ε(A->ε)产生式的文法G。
  输出:一个等价的无左递归文法G‘,但G‘可能具有ε产生式。
  方法:

消除循环左递归算法:
按照某个顺序将非终结符号排列为 A1, A2, ..., An.
for i = (1 to n) {
    for j = (1 to i-1) {
        将每个形如 Ai -> Ajγ 的产生式替换为产生式组 Ai -> δ1γ | δ2γ | ... | δ3γ,
        其中 Aj -> δ1 | δ2 | ... | δk 是所有的 Aj 产生式;
    }
    消除 Ai 产生式之间的立即左递归;
}

算法2:提取左因子

目的:推迟产生式选择。
输入:语法规则G。
输出:等价的提取左因子语法G‘。
方法:对于每个非终结符A,找出最长的公共前缀 α != ε。对于所有 A -> αβ1 | αβ1 | ... | αβn | γ,替换为:
  A -> αA‘ | γ
  A‘ -> β1 | β1 | ... | βn
  
重复这样的行为直到没有同一个非终止符的两个产生式含有公共前缀。

Top-Down Recursive-Descent Parsing

递归下降parser典型过程:void A() {
    Choose an A-production, A ::= X1X2...Xk;
    for i = (i to k) {
        if (Xi is a nonterminal)
            call procedure Xi();
        else if (Xi equals the current input symbol a)
            advance the input to the next symbol;
        else
            call error recovery procedure;
    }
}

FIRST和FOLLOW集

FIRST(α):α是任意一个语法符号,该集合是由α推导出来的句子的第一个终止符的集合。
  计算时,不断应用下列规则,直至没有新的终结符号或ε可以被加入到任何FIRST集为止:
  1) 如果X是一个终止符,则FIRST(X) = {X}。
  2) 如果X是一个非终止符,且存在产生式 X ::= Y1Y2...Yk (k ≥ 1)。如果FIRST(Yi)包含a,并且FIRST(Y1), ... FIRST(Yi-1)都可以推导出ε,那就把a加入到FIRST(X)中。如果所有FIRST(Yi)都包含ε,那就把ε加入FIRST(X)中。
  3) 如果存在 X ::= ε,那就把ε加入FIRST(X)中。

FOLLOW(A):A是一个非终止符,该集合是可以紧跟在A的句型右边的终止符的集合。
  计算时,不断应用下列规则,直至没有新的终结符号被加入到任何FOLLOW集为止:
  1) 如果S是开始符号,则把$添加至FOLLOW(S)中,$是输入串结束标记。
  2) 如果存在产生式 A ::= αBβ,那么FIRST(β)中除了ε之外所有符号都在FOLLOW(B)中。
  3) 如果存在产生式 A ::= αB,或存在产生式 A ::= αBβ 且 FIRST(β) 包含ε,那么FOLLOW(B)包含FOLLOW(A)中所有符号。

时间: 2024-10-29 19:05:32

语法分析原理 - Parsing的相关文章

Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法

Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法 于是我们可以把上面的语法改写成如下形式:1 合并前缀1 语法分析有自上而下和自下而上两种分析方法2 递归下降是现阶段主流的语法分析方法,2 于是我们可以把上面的语法改写成如下形式: 1)       Operator="+" | "-" | "*" | "/" 2)       Expression=<数字>

编译原理--语法制导翻译器(一)

本章重点在前端,特别是词法分析,语法分析和中间代码生成 首先建立一个将中缀算术表达式转换成后缀表达式的语法制导翻译器,然后我们扩展这个翻译器,将某些程序片段转换为如图所示三地址代码 { int i; int j; float[100] a; float v; float x; while(true){ do i = i + 1; while(a[i] < v); do j = j + 1; while(a[j] > v); if(i >= j) break; x = a[i]; a[i]

解密计算机科学(1)

要完全掌握一个学科的精髓,不能从细枝末节开始.人的信心是很重要的,它却是脆弱的,容易被挫败.如果人看到很多细节却看不到全景,他会很快失去信心,他会怀疑要到猴年马月才能掌握一个学科.所以这本书不从细节开始,它也不会给你一个笼统的学科框架,告诉你这个学科包括这么多的"分支",每个分支又包括这么多的"子分支",它们多么博大精深,每个分支都能出很多的专家学者-- 我不想那样吓唬你.也许其它学科是博大精深的,但计算机科学- 大概不是 ;) 你可以在比较短的时间内抓住这个学科的

从输入url开始,完善前端体系架构

原文链接: https://segmentfault.com/a/1190000013662126 从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系! javascript 前端 232 前言 见解有限,如有描述不当之处,请帮忙指出,如有错误,会及时修正. 为什么要梳理这篇文章? 最近恰好被问到这方面的问题,尝试整理后发现,这道题的覆盖面可以非常广,很适合作为一道承载知识体系的题目. 关于这道题目的吐槽暂且不提(这是一道被提到无数次的题,得到不少人的赞同,也被很多人反感),本文的

《你不知道的JavaScript》读书笔记(一)作用域

名词 引擎:从头到尾负责整个 JavaScript 程序的 编译 及 执行 过程. 编译器:负责 语法分析 及 代码生成. 作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限. LHS:赋值操作的左侧(理解为赋值操作的目标是谁,LHS 查询 试图找到变量的容器本身,并对其 赋值 ). RHS:赋值操作的右侧(理解为谁是赋值操作的源头,RHS 查询 就是 查找 某个变量的值). JavaScript 的编译 Java

词法分析器Antlr

一.我们都知道编程语言在执行之前需要先进行编译,这样就可以把代码转换成机器识别的语言,这个过程就是编译. 那么它是怎么编译的呢? Java在JVM虚拟机中进行编译,javascript在Js引擎中编译. 编译的过程一般是三个步骤: 1.分词/词法分析(Tokenizing/Lexing) 这个过程会将由字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token). 2.解析/语法分析(Parsing) 这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表程序

html加载js那些事

浏览器通过内置的JavaScript引擎,读取网页中的代码,对其处理后运行. JavaScript代码嵌入网页的方法 在网页中嵌入JavaScript代码有多种方法. 直接添加代码块 通过script标签,可以直接将JavaScript代码嵌入网页. 1 <script> 2 // some JavaScript code 3 </script> 加载外部脚本 script标签也可以指定加载外部的脚本文件. <script src="example.js"

编译 - 一个超小的编译器

大多数编译可分为三个主要阶段:语法分析(Parsing),转换和代码生成. 语法分析(Parsing)通常为两个阶段:词法分析和语法分析(Syntactic Analysis). 转换:将已经生成的 AST 转化成另一种形式. 代码生成:大多是表示使用 AST 生成代码. jamiebuilds/the-super-tiny-compiler: Possibly the smallest compiler ever The Super Tiny Compiler - README.md 原文地址

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include