精华内容
下载资源
问答
  • 第3章编译原理+词法分析.
  • * 六编写词法分析程序 根据画出的状态转换图识别单词构造词法分析程序每个状态对应一段程序完成到达此状态的工作词法分析程序的控制程序模拟状态转换图的状态转换 在识别标识符的过程中要拼写出来并和保留字区别开来...
  • 编译原理——词法分析

    万次阅读 多人点赞 2019-01-12 21:35:17
    文章目录词法分析(scanning)概述词法分析器的基本功能词法分析器的一些概念词法单元关键字空格,缩进,换行,注释词法的结尾词法错误有穷自动机确定有穷自动机DFA的定义和实现不确定的有穷自动机NFANFA到DFA的转换...

    根据上课内容顺序写的博客,并不是按照书的目录来的
    使用龙书以及编译程序设计原理(第二版)金成植、金英编著
    老师的PPT是英文的,我自己随便翻的,不一定对




    词法分析(scanning)







    概述


        知识关系图
        知识关系图
        开发一个词法分析器是在词法定义的基础上的,词法定义需要使用正则表达式
        正则表达式可以转换为NFA(Non-determinate finite automata 不确定的有穷自动机)
        NFA可以转换为DFA(determinate finite automata确定的有穷自动机)
        DFA可以极小化,进而使用为开发词法分析器的工具


        编译器中词法分析的地位
        地位
        词法分析是编译器中最底层的分析。构造词法分析器的前提是给出语言中单词结构的定义。
        不同语言的单词类别和结构不完全相同,因此不同语言的词法分析器也就不尽相同,但是其构造原理是类似的。
        构造方法可以分为人工方法和自动化方法两种。



    词法分析器的基本功能

    • 输入
      • 源程序
    • 输出
      • 词法单元(token)序列
    • 功能描述
      • 读取源程序
      • 根据源语言的词法定义依次识别单词
      • 构造单词的内部表示——词法单元
      • 检查词法错误
      • 返回词法单元序列

        词法分析器的两种形式

    • 独立
      • 一个词法分析器是编译器中的独立的部分
      • 输出:词法单元的序列
    • 关联
      • 作为语法分析器的一个附属机构
      • 当被语法分析器调用时返回一个词法单元
        两种形式



    词法分析器的一些概念


    词法单元

    • 单词的内部表示是词法单元 token
    • 是编程语言中最小的语法单元
    • 词法单元的表示
    词法单元的类别token-type 词法单元的内容(语义)semantic information
    • token设计示例
    程序表示 ASCII码 单词的类别 单词的内容(语义)
    if 9666 01 9666
    then 478656E6 02 478656E6
    begin 26567696E6 03 26567696E6
    • 一个词法单元包括两个部分
      • 词法单元的类别 token type token.class
      • 词法单元的内容(语义) attributes(semantic information) token.seman
    • 例子
      • <id, “x”>
      • <intNum, 10>

    • token类别
      • 标识符 x, y1, ……
      • 常数 1,12,123,12.3
      • 以下的类别中,每一个示例都可以被看做一个种类
        • 关键字(保留字) int , real, main
        • 操作符 +,-,/,*,<,>,……
        • 分隔符 ;, {, } , ……
    • token内容(语义)
      • 标识符 字符串(变量名、常量名、过程名、数组名等)
      • 常数 数值(整型常数、实型、布尔、字符常数)
      • 关键字(保留字) 关键字表里的数字(语言系统自身定义,通常是字母组成的字符串)
      • 操作符或分隔符 它自己

    关键字

    • 关键字
      • 有特殊意义的单词
      • 不能作为其他意义使用
    • 保留字
      • 被语言系统自身定义的有特殊意义的单词
      • 能作为其他意义使用,需要重载之前的意思
    • 关键字表
      • 用来记录所有的被源程序语言定义的关键字

        例子分析

          
         源程序例子

        源程序例子

         词法单元序列
        词法单元序列


    空格,缩进,换行,注释

    没有语义意义
    只是为了可读性而存在
    可以被移除
    计算行号


    词法的结尾

    • 两种选择情况
      • 读取到了代表程序结尾的符号
        • 例如 PASCAL语言中是 ‘.’
      • 源程序文件的尾部

    词法错误

    • 在词法分析过程中可以发现有限类型的错误主要有两种
      • 非法字符 & ←
      • 第一个字符是错误的 “ /abc”
    • 错误修正
      • 一旦一个词法错误被发现,词法分析器不会停止,会采取措施来继续词法分析的过程
      • 忽视字符流,开始读取下一个字符
      • if &a then x = 12.else …
      • 编译程序设计原理第二版书 P35 【错误修正】 【修正手段】






    有穷自动机



    确定有穷自动机DFA的定义和实现


    DFA的定义


        DFA的正式定义
        一个DFA定义了一个字符串集合
        每个字符串是一个字符的序列,字符属于∑
        起始状态给出生成字符串的起始点
        终端状态给出了终点
        转换函数制定了生成字符串的规则


        确定有穷自动机包含以下五个部分,在一个符号集上可定义出很多不同的自动机。
        每个自动机都是某给定符号集上符号串的识别(接收)器。
        [1]符号集∑(输入符号集)
        [2]状态集合SS={S0,S1,S2,S3,…,Sn}
        [3]开始状态S0
        [4]终止(接受)状态集 {Si1,Si2,…,Sin}
        [5]状态转换器

        DFA的正式定义

    • DFA的特点
      • 一个开始状态
      • 对于一个状态和一个符号,最多只有一条边
    • DFA的功能
      • 定义了一个字符串集合
      • 能被用来定义一个编程语言的词法结构

        两种表示方式

        表:易于实现
        图:易于阅读和理解


        转换表
        包括开始状态S0,终止状态S*,行(字符),列(状态),单元(状态或⊥)
        转换表

        转换图
        均用图形表示,包括开始状态,终止状态(同心圆),状态,边(箭头)
        下图是上述转换表对应的转换图
        转换图


        一些概念

        DFA能接受的字符串

        假设A是一个DFA,a1 a2 a3 … an是一个字符串
        如果存在一个状态序列(S0,S1,S2,…,Sn),满足以下
        状态
        其中S0是开始符号,Sn是接收状态之一,字符串a1 a2 a3 … an可被DFA A 所接受,表示为L(A)


        DFA定义的字符串集

        所有的字符串集中的字符串都是被DFA A所接受的被称为A定义的字符串集,


        无符号实数的DFA实例

    无符号实数


        特殊实例

        自动机的画法,可以按照以下实例来画
        特殊实例


    DFA的实现

    目标(实现DFA的意义)

    • 给出一个定义了一个字符串集规则的DFA
    • 开发一个程序
      • 读取字符串
      • 检查这个字符串是否能被DFA接受

    如果一个字符串能被一个DFA接手

    • 进入下一个状态
    • 在终止状态结束

    如果一个字符串不能被DFA接手

    • 买有下一个状态(⊥)
    • 不会在终止状态停止

    两个方法开发DFA

    • 状态转换表
    • 状态转换图

        基于状态转换表的实现

        输入:一个字符串
        输出:被接受则是true,否则是false
        数据结构:转换表(二维数组T)
        两个变量:流状态CurrentState,流字符CurrentChar
        基本算法:

    1. CurrentState = S0
    2. 读取流字符的第一个字母
    3. 如果流字符不是字符串的最后一个
      如果T(CurrentState,CurrentChar)≠error
          CurrentState=T(CurrentState,CurrentChar)
          读取下一个字符串中的字符作为流字符
          goto 3;
    4. 如果流字符是字符串的最后一个且流状态是终止状态的一个返回true,否则返回false

        实例:
        实例

        基于状态转换表实现的程序结构:
        程序结构


        基于状态转换图的实现

        每一个状态都对应一个case语句
        每一条边都对应一个goto语句
        对于接受状态,添加一个分支,如果流字符是字符串的最后一个则接受
            状态转换图1

        案例    在这里插入图片描述    在这里插入图片描述

        从S0出发,如果遇到a的边,则goto LS1,以此类推
        从S1出发,如果遇到b的边,则goto LS1,以此类推
        ……



        实例:
        在这里插入图片描述

        

    { state 1 }
    if the next character is "/" then
       advance the input; { state 2 }
       if the next character is "*" then
          advance the input;{ state 3 } 
          done: = false;
          while not done do 
           while the next input character is not "*" do
             advance the input;
           end while;
         advance the input; { state 4 }
         while the next input character is  "*" do
           advance the input;
         end while;
         
     if the next input character is "/" then
             done: = false;
          end if;
          advance the input;
        end while;
        accept; { state 5 }
        else{ other processing }
      end if;
      else { other processing }
    end if;
    
    state := 1;{ start }
    while state = 1,2,3 or 4 do
     case state of
     1: case input character of
              "/" :  advance the input;  state := 2;
              else state := ...{ error or other };
         end case;
     2: case input character of
             "*" :  advance the input;  state :=3;
             else state := ...{ error or other };
        end case;
     3: case input character of
            "*" :  advance the input;  state := 4; 
            else advance the input { and stay in state 3 }
        end case;
     4: case input character of
             "/" :  advance the input;state := 5;
             "*" :  advance the input; { and stay in state 4 }
             else advance the input;state :=3;
         end case;
     end case;
    end while;
    if state = 5 then accept else error;
    
    

        实例:

        设二进制数i, 后面跟一个0,产生符号串2i, 后面跟一个1,产生符号串2i+1
        余数: i/3=q, 2i/3=2q

    2i 2i+1
    q=0 0 1
    q=1 2 0
    q=2 1 2

        ∑ = {0,1}
        SS = { S0, S1, S2},
        Sq represents the state that the remainder(余数) is q; (q=0,1,2)

        在这里插入图片描述在这里插入图片描述



    不确定的有穷自动机NFA



    NFA的定义


    非确定有限状态自动机(Nondeterministic Finite Automata,NFA)由以下元素组成:

    一个有限的状态集合S
    一个输入符号集合Σ,并且架设空字符ε不属于∑
    一个状态迁移函数,对于所给的每一个状态和每一个属于∑或{ε}的符号,输出迁移状态的集合。
    一个S中的状态s0作为开始状态(初始状态)
    S的一个子集F,作为接受状态(结束状态)


    与DFA的区别:

    1. 一个状态的不同输出边可标有相同的符号
    2. 允许有多个开始状态
    3. 允许有ε边
    DFA NFA
    开始状态 一个开始状态 开始状态集合
    ε ×
    T(S,a) S’ 或者 ⊥ {S1,S2,…Sn} 或者 ⊥
    实现 容易 不确定性

    NFA实例:

    在这里插入图片描述在这里插入图片描述



    NFA到DFA的转换


    解决两个问题

    • ε边 ε闭包
    • 用相同的符号合并这些边 NextStates(SS,a)

    NFA到DFA的转换

    • 使用一个NFA的状态集作为DFA的一个状态
    • 确保接受相同的字符集合

    计算ε闭包的过程


    对于一个给定的NFA A,和一个状态集SS

    • ε-closure(SS)=SS
    • 如果存在一个属于状态集SS的状态S,状态S有一个ε边指向状态S’,且状态S’不输入ε闭包,添加S’进入ε闭包
    • 重复这个过程直到没有一个状态有ε边能到达不在ε闭包里的状态

    ε闭包——示例
    在这里插入图片描述在这里插入图片描述


    转向状态


    对于一个给定的状态集SS和一个符号a在NFA A中
    转向状态NextStates(SS,a)={s|if there is a state s1∈SS,并且一条边S1→S(边为a)在A中}
    在这里插入图片描述在这里插入图片描述


    算法


    • 对于一个给定的NFA A={∑, SS, SS0, Φ, TS}
    • 生成一个等价的DFA A’={∑, SS’, S0, Φ’, TS’}
    • 步骤
      • S0=ε-closure(SS0), add SS0 to SS’
      • 从SS’中选择一个状态S,对于任意符号a∈Σ
        • 让S’=ε-closure(NextStates(S,a))
        • add(S,a) → S’ to Φ’
        • 如果 S’∉SS’ 添加状态S’到SS’
      • 重复上述步骤直到所有的状态都处理过(无新状态)
      • 对于一个状态S在SS’ S={S1,…,Sn},如果存在Si∈TS 则S是一个接受状态在A’中,添加S进TS’

    PPT例子


    题目

    Σ={a,b,c}
    S0=ε-closure({S0,S10})={S0,S10,S2,S*}

    a b c
    {S0,S10,S2,S*} {S10,S*,S2} {S10,S*,S2} {S*}
    {S10,S*,S2} {S10,S*,S2} {S*}
    {S*} {S*}

    在这里插入图片描述



    书上的例子


    NFA:

    在这里插入图片描述

    因为3是NFA的接受状态号,所以DFA的接受状态是[3]和[1,3],构造过程如下
    在这里插入图片描述

    转换后的DFA如下图
    在这里插入图片描述


    其他例子


    (NFA的确定化)NFA转换为等价的DFA

    NFA转DFA与DFA简化

    子集构造法NFA转换成DFA



    DFA的极小化

    两个DFA的等价:两个DFA接受的字符串集相同
    在这些接受相同字符串集的DFA中,极小化DFA是有最少的状态数的那个DFA
    在这里插入图片描述


    等价状态:对于两个状态S1和S2在同一个DFA中,如果将S1、S2作为开始状态并且他们接受相同的字符串集,S1和S2可以称作等价的状态

    两种极小化DFA的方式:
    状态合并(合并等价状态)
    状态分离(分离不等价状态)

    算法:

    • DFA A = {Σ, SS, S0, Φ,TS}
    • 生成一个等价DFA A’={Σ, SS’, S0’, Φ’,TS’}
    • 分步骤
      • 两个群组 {非终点状态} {终点状态}
      • 选择一个状态SSi集合 SSi={Si1,…,Sin}, 用split(SSi)替换SSi
      • 重复上一步知道所有的群组都不能再分了
      • SS’=群组的集合
      • S0’是由S0组成的群组
      • 如果群组是由A的终态组成的,它也是A’的终态
      • Φ’: SSi→SSj 边为a 如果A中有Si → Sj 边为a Si∈SSi Sj∈SSj

    分离状态集

    已知:
    DFA A = {Σ, SS, S0, Φ,TS}
    状态组 {SS1,…,SSm}, SS1∪…∪SSm=SS
    SSi={Si1,…,Sin}

    split(SSi)是把SSi分成两个群组G1和G2的
    for j=1 to n
        for any a∈Σ
        if (Si1, a) → Sk ^ (Sij, a) → S1 ^ Sk和S1属于同一个群组SSp
              添加Sij到G1
        否则,添加Sij到G2



    简单的例子

    在这里插入图片描述            在这里插入图片描述        在这里插入图片描述






    正则表达式



    正则表达式的定义


    正则表达式Regular Expressions (RE)

    名称 英语 解释
    字母表 alphabet 一个符号的非空有限集合,写成Σ,其中的元素成为符号
    符号串 string 有限的符号序列,使用 λ 或 ε 来表示空串
    符号串长度 length ofstring 字符串中字符的数量,使用β的绝对值来表示字符串β的长度
    符号串连接操作 concatenate operator for strings 两个字符串链接的操作αβ 通常有λβ=βλβ
    符号串集的乘积 product of set of strings 两个字符串集的乘积操作 AB={αβ,α∈A,β∈B}
    符号串集的方幂 power of set of strings A0={λ} A1=A, A2=AA Ak=AA…A(k)
    符号串集的正闭包 positive closure A+=A1∪A2∪A3
    符号串集的星闭包 star closure A*=A0∪A1∪A2∪A3

    {a,ab} {c,d,cd} ={ac,ad,acd,abc,abd,abcd}
    {a,ab}+ = {a,ab}∪{a,ab}{a,ab}∪…
        = {a,ab,aa,aab,aba,abab,……}
    {a,ab}* ={λ}∪{a,ab∪{a,ab}{a,ab}∪…
        = {λ,a,ab,aa,aab,aba,abab,……}


    正则表达式的定义
      每个正则表达式定义一个正则集。若用RE表示Σ上的正则表达式,并用L(RE)表示RE所表示的正则集,则RE的语法定义和相应正则集如下面所述,其中A和B表示正则表达式,并且a表示字母表Σ中的任一符号。

    1. ∅∈RE    L(∅)={ }
    2. ε∈RE     L(ε)={ε}
    3. a∈RE     L(a)={a}
    4. (A)∈RE     L((A))=L(A)
    5. A | B∈RE     L(A | B)=L(A)∪L(B)
    6. A · B∈RE     L(A · B)=L(A)L(B)
    7. A* ∈RE      L(A*)=L(A)*
      在这里插入图片描述

    正则表达式的性质
    在这里插入图片描述


    RE局限性

    • RE不能定义结构比如
      • 配对 pairing
      • 嵌套 nesting
    • RE不能描述那些包括有限重复数的结构(对称性字符串)
    • 例如 WCW W是一个字符串包括a和b
    • (a|b)* c (a|b)* 不能被使用,因为它不能保证字符串在c的两边是总是相同



    正则定义

    正则定义:
    使用RE来定义一个长字符串集是非常不方便的,因此介绍另一种形式的记法,成为形式化定义
    形式化定义的主要目的是为RE中的一些子表达式命名
    例如:
    (1|2|…|9)(0|1|2|…|9)*
    NZ_digit =1|2|…|9
    digit = NZ_digit |0
    NZ_digit digit*


    定义C0的词法结构
    字母letter = a|…|z|A|…|Z
    数字digit = 0|…|9
    自然数NZ-digit = 1|…|9
    保留字Reserved words:
      Reserved = {| }| read| write
    标识符Identifiers: =letter(letter|digit)*
    常量Constant:
      integer: int = NZ-digit digit* | 0
    其他符号Other symbols: syms = +|*| := | ;
    词法结构Lexical structure:
      lex = Reserved | identifier |int | syms



    从正则表达式到DFA的转换


    PPT上例题
    在这里插入图片描述





    从正则表达式(RE)到最小确定性有限状态自动机(DFA)

    正则表达式转DFA

    词法分析:从RE(正则表达式)到DFA(确定的有限状态机)

    正则表达式 :龙书习题

    编译原理习题






    词法分析器的设计和实现

    手动构造一个词法分析器
    使用RE进行词法定义 ,转化为NFA, 转化为DFA, 极小化DFA, 实现即开发一个词法分析器



    用DFA构造一个词法分析器


    • 实现一个DFA
      • 只需要检查一个字符串能不能被DFA接受
    • 实现一个词法分析器
      • 不检查
      • 但是要识别一个可接受的字符串(单词) 并且建立其内部表示
      • <token-type, semantic information>

    一些问题:

    • 独立的DFA还是有联系的DFA(看上一篇博客的内容)
    • 跳过那些特殊字符
      • 空白,缩进,注释,返回(行号)
    • 什么时候停止词法分析
      • 在源文件的末尾
    • 关键字和标识符
    • 怎么知道识别一个词法单元的结束

    立即接受状态和延迟接受状态
    在这里插入图片描述


    C0语言的DFA

    在这里插入图片描述
    保留字/关键字 会被判定,通过在标识符的部分检查保留字/关键字表

    输入:一个符号小序列,在序列结尾是EOF
    输出:词法单元序列

    词法单元数据结构:
    struct Token{
     TkType type;
     char val[50];
    }

    预定义函数

    • bool ReadNextchar()  读取流字符中的流符号,如果符号是EOF返回false,否则返回true

    • int IsKeyword(str)   检查str是否是关键字中的一个,如果是,返回关键字的编码,否则返回-1

    • void SkipBlank()   跳过空白符和return直到读到了流字符的另一个符号


        SkipBlank();
        start:     case CurrentChar of
        “1..9”: str[len] = CurrentChar; len++;  goto IntNum ;
        “a..z”, “A..Z”: str[len] = CurrentChar; len++; goto ID;
        “:”: goto Assign;
        “+” : tk.type =PLUS; SkipBlank() ;goto Done;
        “*”: tk.type = MINUS; SkipBlank() ;goto Done;
        “;” :tk.type = SEMI ; SkipBlank() ;goto Done;
        EOF: exit;
        other: error();
        
        IntNum:
        if  (not ReadNextchar())
        {if len !=0 {tk.type = NUM, strcpy(tk.val, str);
        goto Done}}
        case CurrentChar of
        “0..9”: str[len] = CurrentChar; len++; goto IntNum ;
        other:  tk.type = NUM, strcpy(tk.val, str);
        
        ID:
        if  (not ReadNextchar())
        {if len !=0 {tk.type = IDE, strcpy(tk.val, str);
        goto Done}}
        case CurrentChar of
        “0..9”: str[len] = CurrentChar; len++; goto ID;
        “a..z”, “A..Z”: str[len] = CurrentChar; len++; goto ID;
        other: if  IsKeyword(str)
        {tk.type = IsKeyword(str) }
        else  {tk.type = IDE, strcpy(tk.val, str) };
        goto done;
        
        Assign:
        if  (not ReadNextchar())  {if len !=0 error; exit;};
        case CurrentChar of
        “=”: Tk.type = ASS;
        goto Done ;
        other:error();
      
        Done:
        TokenList[total] = tk;              // add new token to the token list
        total ++;                                    //
        len = 0;                                     //start storing new token string
        strcpy(str, “”);                        // reset the token string
        SkipBlank();                          // skip blank characters
        goto start;                               //start scanning new token
      

    上面这个词法分析器的问题是

    1. str和词法单元序列使用了数组,是不实用的
    2. 没有处理错误
    3. 没有处理行号

    编译原理——词法分析器实现

    根据上面这个词法分析器做了一些小改动,但是依旧不完善

    修改代码(不完整)



    词法分析器的生成器Lex

    flex是由自由软件基金会(Free Software Foundation)制作的GNU编译器包发布的,可以从Internet上免费获得;

    在这里插入图片描述

    课后PPT习题

    1. 画出与正则表达式a(ab|c)*等价的确定有限自动机。
    2. 请用状态分离法将下面的DFA化简请用状态分离法将下面的DFA化简。
    3. 给出自动机DFA的正则表达式。给出自动机DFA的正则表达式。

    第二题图
    在这里插入图片描述
    第三题图
    在这里插入图片描述

    展开全文
  • 编译原理词法分析

    2018-11-28 14:49:06
    首先说明这是网易云课堂中国科学技术大学华保健老师的课程《编译原理》听课笔记,大部分内容是ppt资料,为了方便记忆,写了如下笔记。 词法分析器的任务   首先看编译器结构: 前端又可以分为: 语义分析...

    首先说明这是网易云课堂中国科学技术大学华保健老师的课程《编译原理》听课笔记,大部分内容是ppt资料,为了方便记忆,写了如下笔记。

    词法分析器的任务

     

    首先看编译器结构:

    前端又可以分为:

    语义分析器也叫类型检查器。

    词法分析器结构又为

    词法分析器将代码切分为单词,下面是例子:

     x,y这些就是记号,EOF也是记号,记号是个大集合。

    记号的数据结构定义

    字符流变记号流,首先实现记号的数据结构,用C语言实现如下

    enum kind {IF, LPAREN, ID, INTLIT, …}; //枚举类型,对词法的分类

    struct token{

    enum kind k; //第一个域,类型

    char *lexeme; //具体值

    };

    例子:

    if(x>5)-->

    token{k=if,lexeme=0};

    token{k=LPAREN,lexeme=0};

    token{k=ID,lexeme="x"};

    token{k=GT,lexeme=0};

    ......

    词法分析器的任务:字符流到记号流

    • 字符流:
      • 和被编译的语言密切相关(ASCII, Unicode, or …) 
    • 记号流:
      • 编译器内部定义的数据结构,编码所识别出的词法单元

    手工构造法

    至少两种实现方案:

    • 手工编码实现法
      • 相对复杂、且容易出错
      • 但是目前非常流行的实现方法
        • GCC, LLVM, …
    • 词法分析器的生成器
      • 可快速原型、代码量较少
      • 但较难控制细
    • 我们先讨论第一种实现方案
      • 后面几讲会讨论第二种方案

    手工构造主要问题是转移图的概念

    如下是字符转记号的转移图:

    优化之后:

     

    下面是转移图的算法

    token nextToken () 
        c = getChar (); 
        switch (c) 
            case ‘<’: c = getChar (); 
                      switch (c) 
                          case ‘=’: return LE;
                          case ‘>’: return NE; 
                          default: rollback(); return LT; 
            case ‘=’: return EQ; 
            case ‘>’: c = nextChar (); 
                      switch (c): // similar

     

    如何实现rollback

    加入你正在实现基于图转移算法一个词法分析器,所用的语言是C语言。分别在以下情况下,请问你该如何实现上面的rollback()函数:

    1. 你的词法分析器所分析的程序是直接从文件中读取的;(FILE *)

    2. 词法分析器所分析的程序已经被从文件中读到了一个数组中,然后从数组中读取字符。

    两种做法有什么优劣。

    void rollback()
    {
        fseek(fp, -1, SEEK_CUR); // 这里文件指针假定是全局的了。
    }
     
    void roolback()
    {
        if (nFileIndex >0)
            --g_nFileIndex; // 假定索引为全局变量
    }
    从文件:效率比数组要慢。且异常情况可能会对原文件有误操作,但节省内存
    
    从数组:随着文件的增大,消耗的内存也会提高。但,效率高容易操作。
    
    

    其他符号词法识别

    标识符和关键字关系

    很多语言中的标识符和关键字有交集

    • 从词法分析的角度看,关键字是标识符的一 部分

    以C语言为例:

    • 标识符:以字母或下划线开头,后跟零个或 多个字母、下划线、或数字
    • 关键字:if, while, else, …

    识别关键字(以if为例)

    第一种方案:

    就是把i单独抠出来,当识别到i,从0走到3方向f同理。

    第二种方案:

    对给定语言中所有的关键字,构造关键 字构成的哈希表 H
    对所有的标识符和关键字,先统一按标 识符的转移图进行识别
    识别完成后,进一步查表H看是否是关键 字
    通过合理的构造哈希表H(完美哈希), 可以 O(1)时间完成

    课程中提到了完美哈希(perfect hashing),请结合查询wiki等资料,回答:

    什么是(关键字的)完美哈希?

    如何构造完美哈希?试列举一到两种算法。

    为什么需要构造完美哈希?用关键字单链表是否可以?

    1. 完美哈希函数是没有冲突的的哈希函数,也就是,函数 H 将 N 个 KEY 值映射到 M 个整数上,这里 M>=N ,而且,对于任意的 KEY1 ,KEY2 ,H( KEY1 ) != H( KEY2 ) ,并且,如果 M = = N ,则 H 是最小完美哈希函数(Minimal Perfect Hash Function,简称MPHF)

    2. 打造一个完美的Hash函数,需要针对相应关键字的有限集合来实现,在查阅资料以后发现,先构造两个普通的哈希函数h1(x)和h2(x),还有一个用数组实现的函数g(x)。使得 h(x)=g(h1(x))+g(h2(x))modn ,其中n是参数的总个数,H(x)就是最终的有序最小完美哈希函数了

    3. 编译器需要有更快的速度来完成关键字辨别的速度,构造完美哈希可以提高效率,链式结构的链表不支持随机访问的,而且还要操作指针,效率更低 

     正则表达式

    背景:写一个声明式的规范,通过如lex,flex,jlex,变成词法分析器。

    对给定的字符集∑={c1, c2, …, cn}
    归纳定义:

    • 空串\epsilon是正则表达式
    • 对于任意c\in∑,c是正则表达式
    • 如果M和N是正则表达式, 则以下也是正则表 达式
      • 选择   M | N = {M, N}
      • 连接   MN  = {mn| m\inM, n\inN}
      • 闭包   M*    = {\epsilon, M, MM, MMM, …}//也叫kleene闭包

    正则表达式的形式表示

    e -> \epsilon 

              |  c

              | e | e

              | e e

              | e*
    问题:对于给定字符集={a, b},可以写出哪些正则表达式?

    1.\epsilon 

    2.a,b

    3.\epsilon|\epsilon,a|b,\epsilon|a,\epsilon|b,//选择

    4,\epsilona,\epsilonb,ab,\epsilon\epsilon,....a(\epsilon|a),//连接

    5.\epsilon*,(a(\epsilon|a)*

    引入正则表达式是为了表达程序语言规则,生成词法分析器。下面是如何用正则表达式生成词法分析器的例子。

    关键字

    C语言中的关键字,例如if,while等

    如何用正则表达式表示?

    if:i\in∑,f\in∑,所以连接还是正则表达式。

    C语言中的标识符:以字母或下划线开 头,后跟零个或多个字母、数字或下划 线。
    如何用正则表达式表示?

    这个可以分为两个部分,前半部分是字母加下划线,53种情况,后半部分是再加上数字63种情况。

    然后两部分连接再有个闭包,也是正则表达式。

    C语言中的整型数和浮点数的正则表达式
    如何用正则表达式表示?

    整数(+|-)?[1-9][0-9]*

    浮点数(+|-)? (0|[1-9][0-9]*).[0-9]*

     

    语法糖

    图灵机只需要两种运算就能完整所有操作,赋值和跳转,C或者JAVA是为了更方便,所有所有的语句都是对下层

    这两种运算的封装。也就是说语法糖不是必须的,只是为了更方便。

    可以引入更多的语法糖,来简化构造
    [c1-cn]  == c1|c2|…|cn//顺序,表示c1到cn的任意一个
    e+        == 一个或多个e
    e?         == 零个或一个e
    “a*”== a* 自身, 不是a的Kleen闭包
    e{i, j}    == i到j个e的连接
    .         ==  除‘\n’外的任意字符

    有限状态自动机

    如果要自动生成一个词法分析器,需要写一个声明式的规范,通过一个词法分析器的自动生成工具(flex),生成一个词法分析器,描述输出是什么,这里就是有限状态自动机(FA)。

    就是自动机可以告诉你能不能接收或者识别提供的字符串。可以写成一个元组M,如上图。S是指的有限自动机的状态。q0是自动机一开始的状态,F是结束状态集,转移函数描述怎么动作。

    自动机例子

    下图黄色是状态

    这里∑={a,b},S={0,1,2},q0=0(一般用一个单项箭头代表起始状态),F={2}(一般用双圈代表),\delta如上图,接收就是通过转移函数到最后状态。

    自动机第二个例子

    这是个非确定的状态机(NFA),就是转移是多元素集合,每次转移是个状态集,多个转移状态。这种情况就比较复杂了,因为接受需要回溯状态。

    确定状态有限自动机DFA

    • 对任意的字符,最多有一个状态可以转移
      • \delta:SX∑->S


     非确定的有限状态自动机NFA

    •  对任意的字符,有多于一个状态可以转移
      • \delta:SX(∑\bigcup\epsilon )->\psiS(幂集,子集集合)

    DFA的实现


    是个有向图,边和节点都是有信息的,就是有向图。

    正则表达式到非确 定有限状态自动机

     RE -> NFA:Thompson算法

    基于对RE的结构做归纳

    • 对基本的RE直接构造
    • 对复合的RE递归构造

    递归算法,容易实现

    • 在我们的实现里,不到100行的C代码


    空串和单字符,直接构造,e1e2这种连接的如下构造

    选择自动机形式如下,先构造e1,e2在用4个空,构造。,闭包也如下图

    示例

    a(b|c)*

     

    证明题

    这个论断是否成立:由Thompson算法构造出来的任何一个NFA,均只可能包括唯一的起始状态和唯一的接受状态。

    若成立,请给出证明;若不成立,请给出一个反例。

    成立,证明;

    对于根据epsilon和单个字符的正则表达式构造的NFA只有一个起始状态和一个接受状态。

    对于两个正则表达式e1,e2,假设它们构造出的NFA只有一个起始状态和一个接受状态。那么,对于e1|e2, e1 e2, e1*这三种情况,其结果也都是只有一个起始状态和接受状态的。

    由归纳法可以得出结论成立

    NFA转换到DFA

    思想就是由起始状态出发,先读入任何一个字符,看能走到哪个节点,然后考虑根据\epsilon看能够扩展到哪个节点,然后这些节点做一个集合,构成一个边界,然后从这个边界再找一个点,看能够通过\epsilon扩展到哪个点。构成一个新的集合。

    注意点

    也就是有两步,先状态转换,就是先在NFA上能转换到哪个点,再看新集合上能转换成哪个点,然后对集合上每个点求\epsilon闭包。
    如下图

    子集构造算法

    (* 子集构造算法: 工作表算法*)
    q0 <- eps_closure (n0) //随便取一个节点,看通过epsiono能走到的点,所以q0={0}
    Q <- {q0} //这个点作为初始节点集,加入大Q,Q就是DFA的所有状态机
    workList <- q0 //q0加入工作集
    while (workList != []) 
        remove q from workList 
        foreach (character c) //对每个点都要循环
            t <- e-closure (delta (q, c)) //看通过每个路径能走到哪个节点,发现这个例子只能走道n1,再看这节点能走epsiono闭包到哪个节点,就是先算一个状态,再算这个状态delta的闭包
            D[q, c] <- t 把t(之前的所有能走到的闭包)加到DFA里
            if (t\not\in Q) 
                add t to Q and workList,如果不在大Q,将新qx加入

    代码操作过程就是下面如图: 

    叫子集构造算法是因为在不停构造一个个集合,每个节点都是状态机的子集。工作表算法就是有个worklist存放有待计算的节点。

    对算法的讨论

    不动点算法

    • 算法为什么能够运行终止(循环到worklist为空为止,但是worklist是Q是NFA状态集合,这个n各元素幂集有限,是2^n,所以有限)

    时间复杂度

    • 最坏情况O(2N)
    • 但在实际中不常发生
      • 因为并不是每个子集都会出现

    \epsilon-闭包的计算:深度优先

    复杂度O(n)

    \epsilon-闭包的计算:宽度优先

    就是把一个点的所有能通过\epsilon走到的点加入一个队列,然后向外扩散

    epsilon闭包的计算

    有两种方式可以计算epsilon闭包:

    1. 在线方式:在算法计算的过程中,遇到需要计算某个节点的epsilon闭包的时候,临时计算;

    2. 离线方式:在算法执行之前,把NFA中所有节点的epsilon闭包都计算完;这样算法开始执行后可随时使用。

    你认为这两种方式哪种比较好?原因是什么?

    因为在构造子集的过程中,获取某些节点的Epsilon闭包多次,如果每次需要的时候都计算,这样大大降低了程序效率。所以为了避免重复计算,离线方式才是最好的。但同时也可能一些闭包从未被使用过,有利有弊吧。

    DFA的最小化

    Hopcroft算法

    // 基于等价类的思想 
    split(S) //切分
        foreach (character c) 
            if (c can split S) //c能够切分开一个子集S
                split S into T1, …, Tk
    hopcroft () 
        split all nodes into N, A //先将上面切分的状态分为接收状态和非接收状态,2个集合
        while (set is still changes) //如果两个状态能切分再切
            split(S)

     注意hopcroft通过字符看能不能划分成子集是接受个字符会不会从这个集合出去。

    下面两个示例,第一个示例,划分为N和A,之后通过字符不可能把A切分成开(比如通过b,c)

     

    DFA的代码表示


    概念上讲, DFA是一个有向图

     实际上,有不同的DFA的代码表示

    • 转移表(类似于邻接矩阵)
    • 哈希表(表示关系)
    • 跳转表(跳转代码实现)
    • 。。。

    取决于在实际实现中,对时间空间的权衡

    转移表

    构造个二维数组,x就是DFA的集合数量,y为字符数(如256个的ASCII表),这个就是转移表,还需要词法分析的驱动代码,根据表示表项做控制。代码如下:

    nextToken() //每调用一次,返回识别的串
        state = 0 //目前自动机走到的那个地方
        stack = [] //为了实现最长匹配
        while (state!=ERROR) 
            c = getChar() 
            if (state is ACCEPT) 
                clear(stack) 
            push(state) 
            state = table[state][c]
        while(state is not ACCEPT) 
            state = pop(); 
            rollback();

    跳转表

    nextToken() 
        state = 0 
        stack = [] 
        goto q0
    q0: 
        c = getChar() 
        if (state is ACCEPT) 
            clear (stack) 
        push (state) 
        if (c==‘a’) 
            goto q1:
    q1: 
        c = getChar() 
        if (state is ACCEPT) 
            clear (stack) 
        push (state) 
        if (c==‘b’||c==‘c’) 
            goto q1
    

    从拓扑结构来说,跳转表跟自动机结构一样如下图

    跳转表基本实现是把每个状态变成一段代码,把边的转移变成显式的跳转,每个代码负责识别每个字符的跳转。

    所以跳转表不用维护数组。性能高一些。

    参考资料

    网易云课堂课程:编译原理(中国科学技术大学 华保健)

     

    展开全文
  • 3.5正规文法和有穷自动机 五DFA与NFA的关系 定理对于字母表VT上任一NFAM其接受语言为LM 必存在VT上与M等价的DFAM使得 LMLM 因此对于任一个NFAM我们总能构造出与其等价的DFA M 设NFAM=VT是VT上一个NFA今构造一个VT 的...
  • 词法分析器功能 功能 读源程序的字符序列,逐个拼出单词,并构造相应的内部表示TOKEN.同时检查源程序中的词法错误. 单词 所谓单词是指语言中具有独立含义的最小的语义单位 Token 单词的内部表示编译程序总是用某种程序...
  • 今天学习了编译原理中的词法分析这一章节,我参考了国防工业出版社《编译原理》教材 和中国大学MOOC-国防科技大学《编译原理》的PPT,整理了这一章的内容,希望能够理解这部分的知识。

    1. 背景

    今天学习了编译原理中的词法分析这一章节,我参考了国防工业出版社《编译原理》教材1 和中国大学MOOC-国防科技大学《编译原理》的PPT,整理了这一章的内容,希望能够理解这部分的知识。

    2. 词法分析

    2.1. 编译流程

    开始编译
    单词符号
    语法单位
    中间代码-四元式
    中间代码-四元式
    目标代码
    源程序
    词法分析器
    语法分析器
    语义分析与中间代码生成器
    语义分析与中间代码生成器
    优化段
    目标代码生成器
    编译完成

    Figure 1. 编译流程 \text{Figure 1. 编译流程}

    2.2. 词法分析的任务

    • 词法分析的任务
      • 从左至右逐个字符地对源程序进行扫描,产生一个个单词符号
    • 词法分析器(Lexical Analyzer)
      • 扫描器(Scanner)
      • 执行词法分析的程序

    2.3. 词法分析器的功能

    • 功能
      • 输入源程序、输出单词符号
    • 单词符号的种类
      • 基本字:如 begin,repeat,for,…
      • 标识符:用来表示各种名字,如变量名、数组名和过程名
      • 常数:各种类型的常数
      • 运算符: $ +,-,*,/, \cdots $
      • 界符:逗号、分号、括号和空白

    2.4. 词法分析器的输出

    • 输出的单词符号的表示形式
      • (单词种别,单词自身的值)
    • 单词种别通常用整数编码表示
      • 若一个种别只有一个单词符号,则种别编码就代表该单词符号。假定基本字、运算符界符都是一符一种。
      • 若一个种别有多个单词符号,则对于每个单词符号,给出种别编码自身的值
        • 标识符单列一种;标识符自身的值表示成按机器字节划分的内部码
        • 常数按类型分种;常数的值则表示成标准的二进制形式

    2.5. 词法分析器在编译器中地位

    源程序
    单词符号
    取下一单词
    源程序
    词法分析器
    语法分析器
    符号表

    Figure 2. 词法分析器在编译器中地位 \text{Figure 2. 词法分析器在编译器中地位}

    3. 词法分析器的设计

    3.1. 输入、预处理

    词法分析器工作的第一步是输入源程序文本。输入串一般是放在一个缓冲区中,这个缓冲区称输入缦冲区。词法分析的工作(单词符号的识别)可以直接在这个缓冲区中进行。但在许多情况下,把输入串预处理一下,对单词符号的识别工作将是比较方便的。

    我们可以设想一个预处理子程序,它能够完成去除空白符、换行符和注释还有合并界符等任务。

    每当词法分析器调用它时,它就处理出一串确定长度(如120个字符)的输入字符,并将其装进词法分析器所指定的缓冲区中(称为扫描缓冲区)。这样,分析器就可以在此缓冲区中直接进行单词符号的识别,而不必管其他繁琐事物。

    词法分析器的结构

    Figure 3. 词法分析器的结构 \text{Figure 3. 词法分析器的结构}

    分析器对扫描缓冲区进行扫描时一般用两个指示器,一个指向当前正在识别的单词的开始位置(指向新单词的首字符),另一个用于向前搜索以寻找单词的终点。

    不论扫描缓冲区设得多大都不能保证单词符号不会被它的边界所打断。因此,扫描缓冲区最好使用一个一分为二的区域。并对标识符和常数的长度加以限制(例如,不得多于120个字符)。否则,即使缓冲区再大也无济于事。

    扫描缓冲区

    Figure 4. 扫描缓冲区 \text{Figure 4. 扫描缓冲区}

    3.2. 超前搜索

    • 定义:词法分析过程中,有时为了确定词性,需超前扫描若干个字符。

    如以下FORTRAN语句,用户可以重新定义关键字,编译器就需要超前扫描都关键字后的数字格式才能知道其词性。

    超前搜索

    Figure 5. 超前搜索 \text{Figure 5. 超前搜索}

    除了关键字需要超前搜索,标识符、常数、算符和界符等也可能会需要超前搜索。

    1. 标识符识别

    字母开头的字母数字串,后跟界符或算符

    1. 常数识别

    识别出算术常数并将其转变为二进制内码表示,如

    5.EQ.M 5.EQ.M

    5.E08 5.E08

    1. 算符和界符的识别

    把多字符组成的算符和界符拼合成一个单词符号

    :=.EQ.++>= :=, **, .EQ. , ++,--,>=


    由于超前搜索这个问题的存在,现在的编程语言大多加入了一些限制,从而避免超前搜索。

    1. 所有基本字都是保留字;用户不能用它们作自己 的标识符
    2. 基本字作为特殊的标识符来处理,使用保留字表
    3. 如果基本字、标识符和常数(或标号)之间没有确 定的运算符或界符作间隔,则必须使用一个空白符作间隔,如:

    DO99K=110 DO99K=1,10

    要写成

    DO99K=110 DO \hspace*{0.2cm} 99 \hspace*{0.2cm} K=1,10

    4. 状态转换图

    使用状态转换图是设计词法分析器的一种好途径。转换图是一张有限方向图,可用于识别(或接受)一定的字符串。

    在状态转换图中,

    • 节点代表状态,用圆圈表示
    • 状态之间用箭弧连接。箭弧上的标记(字符)代表在射出结点(即箭弧始结点)状态下可能出现的输出字符或字符类
    • 一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态

    例如,图6表示,从初态进入状态1,若读入字符则进入状态2,若读入数字则进入状态3。

    状态转换图

    Figure 6. 状态转换图 \text{Figure 6. 状态转换图}

    图7中终态节点右上角的星号表示读入其他字符后需要回退到上一个输入,即最终识别出的结果不包含除数字以外的其他字符。

    识别整常数的状态转换图

    Figure 7. 识别整常数的状态转换图 \text{Figure 7. 识别整常数的状态转换图}

    图8是一个词法分析器的设计示例

    词法分析器的设计示例

    Figure 8. 词法分析器的设计示例 \text{Figure 8. 词法分析器的设计示例}

    注:部分内容整理自国防工业出版社《编译原理》教材和中国大学MOOC-国防科技大学《编译原理》PPT

    5. 参考文献

    [1] 陈火旺. 编译原理 [M]. 北京 : 国防工业出版社, 2010.


    联系邮箱:curren_wong@163.com

    Github:https://github.com/CurrenWong

    欢迎转载/Star/Fork,有问题欢迎通过邮箱交流。

    展开全文
  • 目录目录1. 背景2. 词法分析2.1. 编译流程2.2. 词法分析的任务2.3.... 背景今天学习了编译原理中的词法分析这一章节,我参考了国防工业出版社《编译原理》教材[1]和中国大学MOOC-国防科技大学《编译原理》的PPT,...

    7c7ab72c42d765d3c4398e82d70457ed.png

    目录

    • 目录
    • 1. 背景
    • 2. 词法分析
      • 2.1. 编译流程
      • 2.2. 词法分析的任务
      • 2.3. 词法分析器的功能
      • 2.4. 词法分析器的输出
      • 2.5. 词法分析器在编译器中地位
    • 3. 词法分析器的设计
      • 3.1. 输入、预处理
      • 3.2. 超前搜索
    • 4. 状态转换图
    • 5. 参考文献

    1. 背景

    今天学习了编译原理中的词法分析这一章节,我参考了国防工业出版社《编译原理》教材[1]和中国大学MOOC-国防科技大学《编译原理》的PPT,整理了这一章的内容,希望能够理解这部分的知识。

    2. 词法分析

    2.1. 编译流程

    e37e7a6a2f4a68e5d6852b090d288d26.png
    Figure 1. 编译流程

    2.2. 词法分析的任务

    • 词法分析的任务
      • 从左至右逐个字符地对源程序进行扫描,产生一个个单词符号
    • 词法分析器(Lexical Analyzer)
      • 扫描器(Scanner)
      • 执行词法分析的程序

    2.3. 词法分析器的功能

    • 功能
      • 输入源程序、输出单词符号
    • 单词符号的种类
      • 基本字:如 begin,repeat,for,...
      • 标识符:用来表示各种名字,如变量名、数组名和过程名
      • 常数:各种类型的常数
      • 运算符:
      • 界符:逗号、分号、括号和空白

    2.4. 词法分析器的输出

    • 输出的单词符号的表示形式
      • (单词种别,单词自身的值)
    • 单词种别通常用整数编码表示
      • 若一个种别只有一个单词符号,则种别编码就代表该单词符号。假定基本字、运算符界符都是一符一种。
      • 若一个种别有多个单词符号,则对于每个单词符号,给出种别编码自身的值
        • 标识符单列一种;标识符自身的值表示成按机器字节划分的内部码
        • 常数按类型分种;常数的值则表示成标准的二进制形式

    2.5. 词法分析器在编译器中地位

    13b3a5d74f5a78c49c53837ecd0d9ec5.png
    Figure 2. 词法分析器在编译器中地位

    3. 词法分析器的设计

    3.1. 输入、预处理

    词法分析器工作的第一步是输入源程序文本。输入串一般是放在一个缓冲区中,这个缓冲区称输入缦冲区。词法分析的工作(单词符号的识别)可以直接在这个缓冲区中进行。但在许多情况下,把输入串预处理一下,对单词符号的识别工作将是比较方便的。

    我们可以设想一个预处理子程序,它能够完成去除空白符、换行符和注释还有合并界符等任务。

    每当词法分析器调用它时,它就处理出一串确定长度(如120个字符)的输入字符,并将其装进词法分析器所指定的缓冲区中(称为扫描缓冲区)。这样,分析器就可以在此缓冲区中直接进行单词符号的识别,而不必管其他繁琐事物。

    3a0f71b59f224e57331d35f474c88a83.png
    Figure 3. 词法分析器的结构

    分析器对扫描缓冲区进行扫描时一般用两个指示器,一个指向当前正在识别的单词的开始位置(指向新单词的首字符),另一个用于向前搜索以寻找单词的终点。

    不论扫描缓冲区设得多大都不能保证单词符号不会被它的边界所打断。因此,扫描缓冲区最好使用一个一分为二的区域。并对标识符和常数的长度加以限制(例如,不得多于120个字符)。否则,即使缓冲区再大也无济于事。

    28d3983755aeaf58cfd9396d623fe728.png
    Figure 4. 扫描缓冲区

    3.2. 超前搜索

    • 定义:词法分析过程中,有时为了确定词性,需超前扫描若干个字符。

    如以下FORTRAN语句,用户可以重新定义关键字,编译器就需要超前扫描都关键字后的数字格式才能知道其词性。

    83462f3ad91968143af735661979f33e.png
    Figure 5. 超前搜索

    除了关键字需要超前搜索,标识符、常数、算符和界符等也可能会需要超前搜索。

    1. 标识符识别

    字母开头的字母数字串,后跟界符或算符

    2. 常数识别

    识别出算术常数并将其转变为二进制内码表示,如

    3. 算符和界符的识别

    把多字符组成的算符和界符拼合成一个单词符号


    由于超前搜索这个问题的存在,现在的编程语言大多加入了一些限制,从而避免超前搜索。

    1. 所有基本字都是保留字;用户不能用它们作自己的标识符
    2. 基本字作为特殊的标识符来处理,使用保留字表
    3. 如果基本字、标识符和常数(或标号)之间没有确定的运算符或界符作间隔,则必须使用一个空白符作间隔,如:

    要写成

    4. 状态转换图

    使用状态转换图是设计词法分析器的一种好途径。转换图是一张有限方向图,可用于识别(或接受)一定的字符串。

    在状态转换图中,

    • 节点代表状态,用圆圈表示
    • 状态之间用箭弧连接。箭弧上的标记(字符)代表在射出结点(即箭弧始结点)状态下可能出现的输出字符或字符类
    • 一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态

    例如,图6表示,从初态进入状态1,若读入字符则进入状态2,若读入数字则进入状态3。

    23a4db768d0a9535797abb1e9a08b1ed.png
    Figure 6. 状态转换图

    图7中终态节点右上角的星号表示读入其他字符后需要回退到上一个输入,即最终识别出的结果不包含除数字以外的其他字符。

    e25a151286367d522eb960ce1ca42bb0.png
    Figure 7. 识别整常数的状态转换图

    图8是一个词法分析器的设计示例

    0a7aba0889622adeb9647c654abdef36.png
    Figure 8. 词法分析器的设计示例

    注:部分内容整理自国防工业出版社《编译原理》教材和中国大学MOOC-国防科技大学《编译原理》PPT

    5. 参考文献

    [1] 陈火旺. 编译原理 [M]. 北京 : 国防工业出版社, 2010.


    联系邮箱:curren_wong@163.com

    Github:https://github.com/CurrenWong

    欢迎转载/Star/Fork,有问题欢迎通过邮箱交流。

    展开全文
  • 词法分析 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记。 语法分析基础 1. 词法分析程序的功能 词法分析:根据词法规则识别及组合单词,进行词法检查; 对数字常数完成数字字符串到(二进制)数值的...
  • 编译原理》课程是计算机科学与技术专业的必修课程。本课程主要介绍程序设计语言编译程序构造的基本原理和设计方法,包括:编译程序概述、高级语言及其语法描述、词法分析、语法分析、属性文法和语法制导翻译、语义...
  • 参考东南大学廖力老师的编译原理教程和课上PPT内容。 该学习笔记目前仅打算个人使用。 后续会进一步整理,包括添加笔记内容,标明参考资料。 更新中。。。 跳过目录 目录一、词法分析程序的功能二、实现方案1、...
  • *** 蒋宗礼 编译原理 课件,编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标...
  • 参考东南大学廖力老师的编译原理教程和课上PPT内容。 该学习笔记目前仅打算个人使用。 后续会进一步整理,包括添加笔记内容,标明参考资料。 更新中。。。 跳过目录 目录一、单词的种类1、按单词种类分类2、保留...
  • 参考东南大学廖力老师的编译原理教程和课上PPT内容。 该学习笔记目前仅打算个人使用。 后续会进一步整理,包括添加笔记内容,标明参考资料。 更新中。。。 跳过目录 目录一、LEX的功能二、LEX源程序 一、LEX的...
  • 词法分析程序的构造方法分类 讲述正规式正则表达式和有穷自动机理论目的是为了介绍词法分析程序自动构造工具Lex的原理词法分析程序不是通过编程而是执行Lex产生 采用Loop-and-Switch循环和分支方法 本课程采用第二种...
  • 编译原理》课程是计算机科学与技术专业的必修课程。本课程主要介绍程序设计语言编译程序构造的基本原理和设计方法,包括:编译程序概述、高级语言及其语法描述、词法分析、语法分析、属性文法和语法制导翻译、语义...
  • 参考东南大学廖力老师的编译原理教程和课上PPT内容。 该学习笔记目前仅打算个人使用。 由于本菜鸡第一次发csdn,许多格式不会用。后续会进一步整理,包括添加笔记内容,标明参考资料。 更新中。。。 跳过目录 ...
  • 词法分析(科大).ppt 词法分析(中南).ppt 第三章自动机jlh0307.ppt 第三章自动机jlh改.ppt 第四章符号表.PPT 第一章概论.ppt 逆波兰式.ppt 优化.PPT 语法分析-自上而下分析.ppt 语法分析-自下而上分析...
  • 编译原理 教材用的是《编译原理》(第三版)陈火旺著,电子版戳这里。。。 课后习题答案戳这里。。。 教学PPT戳这里。。。 PPT习题答案戳这里。。。 (侵删) 课程设计1——词法分析器 设计题目 手工设计c语言的词法...
  • 第3章 词法分析.ppt;第3章习题的参考答案.doc;第4章_1 自上而下语法分析.ppt;第4章_2 自下而上语法分析.ppt;第4章_3 LR分析方法.ppt;第4章习题参考答案.doc;第5章 语义分析和中间代码生成.ppt;第5章习题参考...
  • 编译原理课设作业,java实现,附上实验报告以及答辩ppt 实现词法分析,语法分析,语义分析
  • 词法分析,语法分析: 解决单词和语言成分的识别及词法和语法结构的检查。语法结构可形式化地用一组产生式来描述。给定一组产生式,我们应该能够将其分析器构造出来。 本章要介绍的是语义分析和代码生成技术。
  • vc源代码合集0951.rar

    热门讨论 2012-06-13 10:25:18
    2012-06-12 11:52 2,753 C++词法分析器.txt 2012-06-12 12:44 2,035,571 Clock.rar 2012-06-12 12:44 1,915,984 CZG.rar 2012-06-12 12:22 10,537 C和C++字符串处理函数.txt 2012-06-12 12:21 8,825 c扫描器源码.txt...

空空如也

空空如也

1 2
收藏数 24
精华内容 9
关键字:

编译原理词法分析ppt