• 【现代编译器】语法分析——正则表达式,上下文无关文法,递归下降分析,分析树


    1 正则表达式

    1 最基础:

    要找一个数字,它可能有一个负号在前面,那么就写上一个负号加上一个问号:  -?

    在JAVA中,\\的意思是“我要插入一个正则表达式的反斜线,表示其后的字符具有特殊的意义”,所以要描述一个整数,正则表达式应该是: \\d。同理,要插入一个普通的反斜线,则应该是:\\\\

    要表示“一个或多个之前的表达式”,应该使用:+

    综上,要表示“可能有一个负号,后面跟着一位或多位数字”,可以这样:  -?\\d+.

    使用正则表达式的最简单途径——String类的内建功能:

    匹配:“-1234”.matches("-?\\d+");

    切分:split()方法,将字符串从正则表达式匹配的地方切开。string.split("n\\W+"); 表示字母n后面跟着一个或多个非单词字符。被匹配的字符串是不出现在切分结果中的。

    替换:替换正则表达式第一个匹配的子串,或是替换所有匹配的地方。 s.replaceFirst("f\\w+", "located");    s.replaceAll(“shrubbery|tree|herring”, "banana");

       

    如果正则表达式不是只使用一次的话,非String对象的正则表达式明显具备更佳的性能。这个在稍后就会看到。


    例:下面的每一个正则表达式都能成功匹配字符序列“Rudolph”

    for(String pattern: new String[]{
            "Rudolph", "[rR]udolph", "[rR][aeiou][a-z].*", "R.*" })
    })
            System.out.println("Rudolph".matched(pattern));

    2 量词

    量词描述了一个模式吸收输入文本的方式

    • 贪婪型:为所有可能的模式发现极可能多的匹配
    • 勉强型:匹配满足模式所需要的最少字符数
    • 占有型:只能用于Java。
    测试代码:
    import java.util.regex.*;
    
    public class testRegex
    {
    	public static String t = "Java now has regular expressions";
    
    	public static String r = "((^[aeious])|(\s+[aeiou]))"
    	{
    		System.out.println("Input: \"" + args[0] + "\"");
    
    				for(String arg: args)
    					{
    				System.out.println("Regular expression: \"" + arg + "\"");
    			    Pattern p = Pattern.compile(arg);
    				Matcher m = p.matcher(t);
    				while(m.find())
    					{
    						System.out.println("Match \"" + m.group() + "\" at position" + m.start() + "-" + (m.end()-1));
    					}
    			}
    	}
    }


    功能更强大的正则表达式工具:
    1. 导入java.util.regex包,然后用static Pattern.compile()方法编译你的正则表达式,生成一个Pattern对象
    2. 把要检索的字符串传入Pattern对象的matcher()方法,matcher方法会生成一个Matcher对象,该对象有很多方法,如
      • boolean matches():匹配整个输入的字符串是否匹配正则表达式
      • bollean lookingAt():判断该字符串(不必是整个字符串)的某一部分是否能够匹配模式。
      • bollean find():在字符串中查找多个匹配,用Matcher.group()返回查找到的匹配的字符串。
      • boolean find(int start)

    2 正题——语法分析

    简单的看了一下Java中正则表达式的基本知识,下面仔细看一看在虎书中语法分析的章节。

    2.1 词法分析器实现正则表达式

    匹配括号对于有限自动机是不可识别的。
    在翻译成有限自动机以前,在所有正则表达式出现digits的地方都简单地用右边的式子代替。
    简化的概念并没有增前正则表达式的描述能力,除非简化形式是递归的。这种递归附加功能正式在语法分析中所需要的,一旦使用了递归简化形式,就不再需要进行迭代,除非是表达式的首部。
    定义:
    expr = ab(c|d)e
    可以用附加定义重写:
    aux = c  d
    expr = a b aux e

    为了避免使用交替符号,对于同一符号,可以使用一些辅助扩充:
    aux = c
    aux = d
    expr = a b aux e

    另外一个i例子:
    expr = (a b c)*

    重写为:
    expr = (a b c)expr
    expr = &

    2.2 上下文无关文法CFG

    CFG = <T, N, P, S>
    T:终结符    N:非终结符   P:产生式集合    S:初始非终结符

    正如正则表达式可以静态声明的方式定义词法结构一样,文法也可以用声明的方式定义语法结构,但需要比有限自动机更强大的方式来分析文法描述的语言。

    对于语法分析,字符串就是源程序,符号就是词法记号,字母表就是词法分析器返回的记号类型集。

    文法的产生式集: symbol -> symbol symbol ... symbol
    有0个或多于0个的记号在产生式的右边,这些符号要么是终结符,即描述语言中字符串在字母表中的记号;要么是非终结符,即出现在产生式左边的记号。产生式左边不会出现终结符的记号。最后,还需要使用一个非终结符作为文法的开始符号。

    推导:从开始符号出发,对于任一非终结符,用其产生式的右侧部分进行替换并重复进行这一操作。


    2.3 分析树

    分析树就是将推导式中的每个符号同其派生符号连接而成。

    二义性文法:若一个文法可以用两棵不同的分析树派生出同一个句子,那么该文法就是二义性的。
    如何避免二义性,即如何将二义性文法转换成非二义性文法:
    途径:引入一些非终结符号可以得到非二义性文法:
    文法3.5为二义性文法:

    引入T和F后所得的非二义性文法:

    符号E T 和F分别代表表达式、项和因子。习惯上,因子用于乘法,项用于加法。

    综上,消除二义性的通常做法是转换文法,虽然这些文法只是在文法上存在二义性,但是它们在编程时也会出现二义性。

    通常,使用$符号代表全文的结束,即分析器读入的终结符。
    文法3.8加入终结符后的文法:


    2.4 预测分析——递归下降分析

    • 每一个非终结符定义成一个递归函数
    • 每一个右部写成函数的一个分情况讨论
    把每个文法产生式转换成一个递归函数的子句。


    递归下降分析器对应每个非终结符都有一个函数,对应每个产生式都有一个子句。




    递归下降、预测或者分析仅限于如下的文法中:每个子表达式的第一个终结符号为选择产生式提供了足够多的信息。这样们需要引入一个FIRST集的概念才能推导出一个无冲突递归下降分析器。

    PS: 虎书太难懂了,今天就先到这吧。。



  • 相关阅读:
    io与网络
    画图联系
    Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常
    OracleHelper> Oracle数据库连接类及测试
    (转)如何将自己的Web项目部署在IIS中并运行(C# .NET ASP vs2019 详细教程 <原创内容>)
    如何进行Oracle安装TNS_ADMIN环境变量设置,所有数据库的tns_admin值都可以设置为单个位置,从而允许服务器上所有数据库使用一组SQL*Net文件
    @ConfigurationProperties注解原理与实战
    @ConfigurationProperties注解使用
    ODAC 安裝 (11.2.4)
    使用 IIS 部署web项目至 Windows 服务器到可以访问的详细操作
  • 原文地址:https://www.cnblogs.com/suzhou/p/3638990.html
Copyright © 2020-2023  润新知