How To Build a Yacc?(2)

博客介绍了如何识别代码是否符合定义的文法,先将代码文本转化为符号流,采用递归下降分析技术,以function_decl文法为例阐述识别方法。还介绍了first集合概念,最后总结编写递归下降解析程序的规律,该技术对多数简单语法规则有效。
如何识别一段代码是否符合定义的文法?

如上面的例子:
function foo(kick, so, by);

首先,技术上来说,代码文本是一段字符流,f, u, n, c....,而我们文法识别的最小级别是符号(token), 所以需要将其转化为符号流,这个功能可以很容易的用lex实现,这个步骤不是讲述重点,不加详细叙述。

最直接的识别方法,以function_decl文法为例,我们从符号流中取一个当前符号,然后判断这个符号是否属于开始符号(function_decl)的某个产生式的第一个符号, 如果找到了这样一个产生式,那么认为应该按照这个产生式进行展开,匹配并丢弃当前这个符号,并期望符号流中余下的符号能匹配该产生式剩余的符号;那么继续从符号流中取去下一个符号,继续上面的步骤。

如果要用一个算法来描述它,那么看起来,象这个样子。
// 匹配一个符号token...
void match(token)
{
    if (current_token == token) current_token = get_next_token();
    else error("expect {token}, but give {current_token}")
}

// function_decl 用来匹配一个函数声明语句;
// function_decl 的产生式为:
// function_decl := function func_name ( argment_list );
void function_decl( )
{
    current_token = get_next_token();   // 取出一个符号
    match(function);   // 匹配function
    func_name();       // 如果已经匹配,那么接下来应该匹配函数名字了
    match('(');            // 匹配'('
    argument_list();   // 接下来应该参数列表
    match(')');            // 匹配')'
}

void func_name()
{
    match(id);
}

void argument_list()
{
    while (current_token == id) {
       match(",");
    }
}


如此简单?是不是?
以上的分析技术被称为递归下降分析技术,它对大多数简单的语法规则非常有效。
这种分析方法可以很容易的被归纳成一些简单的规则,根据这些规则,我们可以方便的编制分析程序。
在阐述这些规则之前,有必要介绍一个概念:fisrt集合。

什么是fisrt集合?
一个产生式的first项目就是这个产生式(production)的匹配第一个非终结符号。一套文法的所有产生式的first项目组成了first集合。求解first集合的方法:对于production: S = ABC
first(ABC) , 如果A是一个terminal, 那么first(ABC)= A, 如果A是一个NONTERMINAL, 那么first(ABC) = first(A), 如果A最终被推出一个空的符号,那么first(ABC)  = first(BC), 依次类推。
这个概念之所以重要,是因为在递归下降算法中,在匹配一个非终结符的过程中,需要检测当前符号流中的符号是否属于该非终结符的所有产生式的first集合;如果属于,则用该产生式来扩展这个非终结符。

如何编写递归下降解析程序?
是时候总结一下规律了,对于每个产生式a来说,我们定义T(a) 是匹配a的程序代码:

when: a = A (A是terminal)
T(a):
 if (t == A) t = get_next_token();
else error    (t 是当前符号,get_next_token取得下一个符号)

when: a = X (X是nonterminal)
T(a): X();  定义一个X的函数,实现由X的产生式定义。

when: a = a1 | a2 | a3 | ... | aN
T(a):
if (t <- First(a1) ) T(a1)
else if (t <- First(a2)) T(a2)
...
else if (t <- First(aN)) T(aN)
else error

when: a = a1 a2 ... aN
T(a): T(a1) T(a2) ... T(aN)

when: a = {a1}
T(a): while (t <- First(a1)) T(a1)







checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu loading site script './config.site' loading build-specific script './config.site' checking for pwd... /usr/bin/pwd checking whether builddir is srcdir... yes checking whether ln -s works... yes checking for ar... ar checking for a BSD-compatible install... /usr/bin/install -c checking for sed... /usr/bin/sed checking for which... /usr/bin/which checking for less... /usr/bin/less checking for gtar... no checking for gnutar... no checking for tar... /usr/bin/tar checking for tex... no checking for pdftex... no configure: WARNING: you cannot build PDF versions of the R manuals checking for pdflatex... no configure: WARNING: you cannot build PDF versions of vignettes and help pages checking for makeindex... no checking for texi2any... no configure: WARNING: you cannot build info or HTML versions of the R manuals checking for texi2dvi... no checking for kpsewhich... no checking for latex inconsolata package... checking for unzip... /usr/bin/unzip checking for zip... /usr/bin/zip checking for gzip... /usr/bin/gzip checking for bzip2... /home/linzhuojun/miniconda3/envs/DeepMineLys/bin/bzip2 checking for xdg-open... /usr/bin/xdg-open using default browser ... /usr/bin/xdg-open checking for xdg-open... /usr/bin/xdg-open checking for working aclocal... missing checking for working autoconf... missing checking for working autoheader... missing checking for bison... no checking for byacc... no checking for yacc... no checking for notangle... false checking for realpath... /usr/bin/realpath checking for pkg-config... /usr/bin/pkg-config checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether the compiler supports GNU C... yes checking whether gcc accepts -g... yes checking for gcc option to enable C11 features... none needed checking for stdio.h... yes checking for stdlib.h... yes checking for string.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for strings.h... yes checking for sys/stat.h... yes checking for sys/types.h... yes checking for unistd.h... yes checking for wchar.h... yes checking for minix/config.h... no checking for sys/time.h... yes checking for sys/param.h... yes checking whether it is safe to define __EXTENSIONS__... yes checking whether _XOPEN_SOURCE should be defined... no checking how to run the C preprocessor... gcc -E looking for a modern Fortran compiler checking for gfortran... no checking for g95... no checking for xlf95... no checking for f95... no checking for fort... no checking for ifort... no checking for ifc... no checking for efc... no checking for pgfortran... no checking for pgf95... no checking for lf95... no checking for ftn... no checking for nagfor... no checking for xlf90... no checking for f90... no checking for pgf90... no checking for pghpf... no checking for epcf90... no checking for g77... no checking for xlf... no checking for f77... no checking for frt... no checking for pgf77... no checking for cf77... no checking for fort77... no checking for fl32... no checking for af77... no checking whether the compiler supports GNU Fortran... no checking whether accepts -g... no configure: error: No Fortran compiler found
最新发布
11-18
(base) lenovo@lenovo-V2:/mnt/65f6468a-2da7-47c8-bbfa-e1bbde34b290/R-4.5.0$ ./configure checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu loading site script './config.site' loading build-specific script './config.site' checking for pwd... /usr/bin/pwd checking whether builddir is srcdir... yes checking whether ln -s works... yes checking for ar... ar checking for a BSD-compatible install... /usr/bin/install -c checking for sed... /usr/bin/sed checking for which... /usr/bin/which checking for less... /usr/bin/less checking for gtar... no checking for gnutar... no checking for tar... /usr/bin/tar checking for tex... /usr/bin/tex checking for pdftex... /usr/bin/pdftex checking for pdflatex... /usr/bin/pdflatex checking for makeindex... /usr/bin/makeindex checking for texi2any... /usr/bin/texi2any checking whether texi2any version is at least 6.1... yes checking for ginstall-info... /usr/bin/ginstall-info checking for texi2dvi... /usr/bin/texi2dvi checking for kpsewhich... /usr/bin/kpsewhich checking for latex inconsolata package... missing configure: WARNING: neither inconsolata.sty nor zi4.sty found: PDF vignettes and package manuals will not be rendered optimally checking for unzip... /usr/bin/unzip checking for zip... /usr/bin/zip checking for gzip... /usr/bin/gzip checking for bzip2... /home/lenovo/miniconda3/bin/bzip2 checking for xdg-open... /usr/bin/xdg-open using default browser ... /usr/bin/xdg-open checking for xdg-open... /usr/bin/xdg-open checking for working aclocal... missing checking for working autoconf... missing checking for working autoheader... missing checking for bison... no checking for byacc... no checking for yacc... no checking for notangle... false checking for realpath... /usr/bin/realpath checking for pkg-config... /usr/bin/pkg-config checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether the compiler supports GNU C... yes checking whether gcc accepts -g... yes checking for gcc option to enable C11 features... none needed checking for stdio.h... yes checking for stdlib.h... yes checking for string.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for strings.h... yes checking for sys/stat.h... yes checking for sys/types.h... yes checking for unistd.h... yes checking for wchar.h... yes checking for minix/config.h... no checking for sys/time.h... yes checking for sys/param.h... yes checking whether it is safe to define __EXTENSIONS__... yes checking whether _XOPEN_SOURCE should be defined... no checking whether gcc -std=gnu23 is a C23 compiler... no checking whether gcc -std=gnu2x is a C23 compiler... no configure: WARNING: C23 support is unavailable checking how to run the C preprocessor... gcc -E looking for a modern Fortran compiler checking for gfortran... no checking for g95... no checking for xlf95... no checking for f95... no checking for fort... no checking for ifort... no checking for ifc... no checking for efc... no checking for pgfortran... no checking for pgf95... no checking for lf95... no checking for ftn... no checking for nagfor... no checking for xlf90... no checking for f90... no checking for pgf90... no checking for pghpf... no checking for epcf90... no checking for g77... no checking for xlf... no checking for f77... no checking for frt... no checking for pgf77... no checking for cf77... no checking for fort77... no checking for fl32... no checking for af77... no checking whether the compiler supports GNU Fortran... no checking whether accepts -g... no configure: error: No Fortran compiler found
11-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值