• 正则表达式与上下文无关文法


    保留版权,转载需注明出处(潘军彪的CSDN博客http://blog.csdn.net/panjunbiao

    正则表达式

    正则表达式在日常开发中时不时都会遇到,我们先来看看正则表达式( Regular Expression)的定义(参考龙书英文第2版121页):

    1. ε是一个正则表达式,它生成的语言L(ε)等价于{ε},即L(ε)={ε},就是一个空字符串
    2. 如果a属于符号集Σ,那么a也是一个正则表达式,且其生成的语言L(a)={a},就是一个a字符
    3. 如果r和s都是正则表达式,那么r | s也是正则表达式,L(r | s) = L(r) ∪ L(s)
    4. 如果r和s都是正则表达式,那么r s也是正则表达式,L(r s) = L(r) L(s)
    5. 如果r是正则表达式,则r*也是正则表达式,L(r*)=(L(r))*
    6. 如果r是正则表达式,则(r)也是正则表达式,L((r))=L(r)
    来看看正则表达式的一些简单例子,假设字符表Σ是全部的小写字母(a~z)以及阿拉伯数字(0~9),则:
    a
    abc
    a|b
    ab|bc
    a*
    (ab)*
    (a|b)(0|1)*
    都是正则表达式。

    正则定义

    有时一个正则表达式很复杂,我们希望能够把这个正则表达式用记号记下来,以便以后使用,于是就有了正则定义(Regular Definitions)(参考龙书英文第2版123页):
    设Σ是符号表,如果有一系列的定义:
    d1 → r1
    d2→ r2
    ...
    dn→ rn
    并且:
    1. 任一个di都是一个新的符号,它既不属于Σ,也不属于{d1,d2,d3,...,d(i-1)}
    2. 任一个ri都是一个正则表达式,能够由符号表Σ以及{d1,d2,d3,...,d(i-1)}所表示
    这样就构成了一组正则表达式定义。

    上下文无关文法

    上下文无关文法(Context-Free Grammar)的定义参考龙书英文第2版197页:
    1. 终结符号(Terminals)
    2. 非终结符号(Nonterminals)
    3. 一个非终结符号作为开始符号
    4. 一组产生式
    稍详细的内容可见我的另一篇博文 到底什么是上下文无关文法?

    正则定义与上下文无关文法的区别

    正则定义与上下文无关文法的重要区别在于,在正则定义中是不允许递归定义的,例如A → aA|b不是一个正则定义,为其左边的A必须是一个新的符号,也就是说不能在其他地方定义过,胆识其右边要求每一个符号都是定义过的,因此这个定义无法满足。而上下文无关文法则没有这个约束,因此A → aA|b是一个上下文无关文法的产生式,但不是正则定义的定义式。
    看过一段话,意思是正则表达式在编译器构建中一般用来进行词法分析,通过NFA、DFA就可以识别,而更复杂的文法就需要以来其他算法了。
    Regular expressions and BNF are two grammatical formalisms for describing sets of strings. Regular expressions are a concise and convenient notation for describing syntax when "nesting" is not an issue. BNF is a more powerful notation that allows for the description of nested language constructs using nonterminal symbols in arbitrary recursive combinations. Thus regular expressions are appropriate for token-level syntax of programming languages, while BNF is required for the higher-level recursive syntax of expressions, statements and so on.
    原文请看 http://www.cs.sfu.ca/~cameron/Teaching/D-Lib/RegExp.html

    运用正则定义的要求,我们可以从上下文无关文法中,筛选出符合正则定义的产生式,这些符合正则定义的产生式,就可以用来生成有限状态自动机。
    下面的类实现了从上下文无关文法产生式中筛选处正则定义式:
    /*
        This file is one of the component a Context-free Grammar Parser Generator,
        which accept a piece of text as the input, and generates a parser
        for the inputted context-free grammar.
        Copyright (C) 2013, Junbiao Pan (Email: panjunbiao@gmail.com)
    
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        any later version.
    
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
    
        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    package analyzer;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import abnf.Rule;
    import abnf.RuleName;
    
    public class RegularAnalyzer {
    	private List<Rule> nonRegularRules = new ArrayList<Rule>();
        public List<Rule> getNonRegularRules() { return nonRegularRules; }
    
    	private List<Rule> regularRules = new ArrayList<Rule>();
    	public List<Rule> getRegularRules() { return regularRules; }
    
        private List<Rule> undefinedRules = new ArrayList<Rule>();
        public List<Rule> getUndefinedRules() { return undefinedRules; }
    
    	public RegularAnalyzer(List<Rule> rules) {
    		Set<RuleName> definedRuleNames = new HashSet<RuleName>();
            List<Rule> observedRules = new ArrayList<Rule>();
            observedRules.addAll(rules);
    
    		boolean foundRegular;
    		do {
    			foundRegular = false;
    			for(int index = observedRules.size() - 1; index >= 0; index --) {
                    Set<RuleName> dependent = observedRules.get(index).getElements().getDependentRuleNames();
                    if (definedRuleNames.containsAll(dependent)) {
                        definedRuleNames.add(observedRules.get(index).getRuleName());
                        regularRules.add(observedRules.get(index));
                        observedRules.remove(index);
                        foundRegular = true;
                        continue;
                    }
    
                    if (!dependent.contains(observedRules.get(index).getRuleName())) {
                        continue;
                    }
    
                    dependent.remove(observedRules.get(index).getRuleName());
                    if (definedRuleNames.containsAll(dependent)) {
                        definedRuleNames.add(observedRules.get(index).getRuleName());
                        nonRegularRules.add(observedRules.get(index));
                        observedRules.remove(index);
                        foundRegular = true;
                    }
    			}
    		} while (foundRegular);
            undefinedRules.addAll(observedRules);
            observedRules.clear();
    	}
    }
    
     
  • 相关阅读:
    【ARTS】打卡第七周
    【ARTS】打卡第六周
    【ARTS】打卡第五周
    【leetcode】 438. Find All Anagrams in a String
    【ARTS】打卡第四周
    【ARTS】打卡第三周
    【leetcode】 11. Container With Most Water
    【ARTS】打卡第二周
    【ARTS】打卡第一周
    深度VS广度——谈谈对测试职业的一些思考
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3198879.html
Copyright © 2020-2023  润新知