基於Predictive Parsing的ABNF語法分析器(六)——AbnfParser文法解析器之多個符號連接的情形(如rule和CRLF)

基於預測的文法分析器,一個明顯的特點就是將非終結符定義爲解析函數(方法),當非終結符號可以派生爲其他非終結符號時,在解析函數中遞歸調用即可。這種方法的一個缺點,是難以處理需要回溯的情形,後面我們再詳細分析。上次我們研究了諸如CR、LF、HTAB等單個字符的解析,這一篇來看看稍微複雜一點的多個符號連接的情形,包括CRLF和RULE兩個符號。
/*
    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: [email protected])

    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/>.
 */

//  CRLF           =  CR LF
	protected String CRLF() throws IOException, MatchException {      
//      回車和換行符號,直接調用相應的CR、LF方法來進行解析就OK。
		return CR() + LF();
	}

    //  CRLF           =  CR LF
    @Test
//  測試CRLF方法的單元測試方法
    public void testCRLF() throws Exception {
//  創建一個測試器,在測試器的test方法中調用被測方法CRLF()
        Tester<String> tester = new Tester<String>() {
            @Override
            public String test(AbnfParser parser) throws MatchException, IOException {
                return parser.CRLF();
            }
        };
//      對於字符串0x0D + 0x0A,斷言解析成功
        Assert.assertEquals(String.valueOf((char)0x0D) + String.valueOf((char)0x0A), AbnfParserFactory.newInstance(new char[] {0x0D, 0x0A}).CRLF());

//      對於字符串0x0D + 0x0A + 0x0C,斷言解析成功,但最後面的0x0C不應該被解析。
        Assert.assertEquals(String.valueOf((char)0x0D) + String.valueOf((char)0x0A), AbnfParserFactory.newInstance(new char[] {0x0D, 0x0A, 0x0C}).CRLF());
//      對於字符串0x0D + 0x0A + 0x0D,斷言解析成功,但最後面的0x0D不應該被解析。
        Assert.assertEquals(String.valueOf((char)0x0D) + String.valueOf((char)0x0A), AbnfParserFactory.newInstance(new char[] {0x0D, 0x0A, 0x0D}).CRLF());
//      對於字符串0x0D + 0x0A + 0x0A,斷言解析成功,但最後面的0x0A不應該被解析。
        Assert.assertEquals(String.valueOf((char)0x0D) + String.valueOf((char)0x0A), AbnfParserFactory.newInstance(new char[] {0x0D, 0x0A, 0x0A}).CRLF());
//      對於空字符串0x0D + 0x0A + 0x0C,斷言解析異常
        Assertion.assertMatchException("", tester, 1, 1);
//      對於字符串0x0D,斷言解析異常
        Assertion.assertMatchException("" + (char)0x0D, tester, 1, 1);
//      對於字符串0x0A,斷言解析異常
        Assertion.assertMatchException("" + (char)0x0A, tester, 1, 1);
    }

//		        rule           =  rulename defined-as elements c-nl
//      解析rule的方法
	protected Rule rule() throws IOException, MatchException {
//              rule的第一個元素是rulename,首先調用rulename()方法,並記錄解析到的規則名
		RuleName rulename = rulename();

//              rulename後面緊接着defined-as元素,調用相應的方法
		String definedAs = defined_as();

//              defined-as後面接着elements元素,調用elements()
		Elements elements = elements();

//              elements後面接着c-nl元素,調用之。
		c_nl();

//              返回解析到的規則
		return new Rule(rulename, definedAs, elements);
	}

    //		        rule           =  rulename defined-as elements c-nl
    @Test
    public void testRule() throws Exception {
//      創建測試器
        Tester<Rule> tester = new Tester<Rule>() {
            @Override
            public Rule test(AbnfParser parser) throws MatchException, IOException {
                return parser.rule();
            }
        };

        String input;
        Elements elements;
        elements = AbnfParserFactory.newInstance("b").elements();
//      a=b是一條符合文法的規則
        Assertion.assertMatch("a=b" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=", elements), 1, 2);

//      a=/b是一條符合文法的規則
        Assertion.assertMatch("a=/b" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=/", elements), 1, 2);

        elements = AbnfParserFactory.newInstance("b/c").elements();
        Assertion.assertMatch("a=b/c" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=", elements), 1, 2);
        Assertion.assertMatch("a=/b/c" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=/", elements), 1, 2);

        elements = AbnfParserFactory.newInstance("b c d").elements();

//      a=b c d是一條符合文法的規則
        Assertion.assertMatch("a=b c d" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=", elements), 1, 2);

//      a=/b c d是一條符合文法的規則
        Assertion.assertMatch("a=/b c d" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=/", elements), 1, 2);

        elements = AbnfParserFactory.newInstance("[b]").elements();

//      a=[b]是一條符合文法的規則
        Assertion.assertMatch("a=[b]" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=", elements), 1, 2);

//      a=/[b]是一條符合文法的規則
        Assertion.assertMatch("a=/[b]" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=/", elements), 1, 2);

        elements = AbnfParserFactory.newInstance("*b").elements();

//      a=*b是一條符合文法的規則
        Assertion.assertMatch("a=*b" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=", elements), 1, 2);

//      a=/*b是一條符合文法的規則
        Assertion.assertMatch("a=/*b" + (char)0x0D + (char)0x0A, tester, new Rule(new RuleName("a"), "=/", elements), 1, 2);
    }
下一篇我們將分析更復雜的文法。

本系列文章索引:基於預測的ABNF文法分析器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章