基於Predictive Parsing的ABNF語法分析器(九)——AbnfParser文法解析器之帶星號的情形(c-wsp和comment)

直接上代碼吧,都寫到註釋裏面了。

/*
    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/>.
 */
//    c-wsp          =  WSP / (c-nl WSP)
	protected String c_wsp() throws IOException, MatchException {
//              由於c-wsp可以派生爲WSP或者c-nl WSP,當我們向前看字符輸入流時,
//              需要看這兩個產生式的第一個字母,在龍書中也就時求FIRST(WSP)和
//              FIRST(c-nl WSP)兩個函數,其中:
//              FIRST(WSP) = {0x20, 0x09};
//              FIRST(c-nl WSP) = {';', 0x0D};
//              我們開心的看到,FIRST(WSP)和FIRST(c-nl WSP)沒有交集,
//              因此只需要向前看一個字符就足夠了。
		switch (is.peek()) {
            case 0x20: case 0x09: return WSP();
		    case ';':case 0x0D: return c_nl() + WSP();
		    default: throw new MatchException("[0x20, ';']", is.peek(), is.getPos(), is.getLine());
		}
	}

    //WSP            =  SP / HTAB
    //  VCHAR          =  %x21-7E
    //    comment        =  ";" *(WSP / VCHAR) CRLF
    //		        c-nl           =  comment / CRLF
    //    c-wsp          =  WSP / (c-nl WSP)
    @Test
    public void testC_wsp() throws MatchException, IOException, Exception {
        Tester<String> tester = new Tester() {
            public String test(AbnfParser parser) throws MatchException, IOException {
                return parser.c_wsp();
            }
        };

        Assertion.assertMatch("" + (char)0x20, tester, 2, 1);
        Assertion.assertMatch("" + (char)0x09, tester, 2, 1);
//        TODO
//        Can not handle this case
//      由於我們的算法不支持回溯,當分析c-wsp的時候,如果第一個字符是0x0D,
//      上面的分析程序就會認爲這是c-nl的第一個字符,因而進入c_nl()+WSP()的代碼
//      但是在這個測試用例中,我們的0x0D後面卻沒有跟着0x0A,
//      也就是說這個c_nl()的分析過程實際上是不能成功的,
//      而讀指針又不能回溯到c_nl()之前,所以只能是拋出異常了。
        Assertion.assertMatchException("" + (char)0x0D + (char)0x09, tester, 1, 1);
        Assertion.assertMatch("" + (char)0x20 + (char)0x20, tester, 2, 1);
        Assertion.assertMatch("" + (char)0x0D + (char)0x0A + " ", tester, 2, 2);
        Assertion.assertMatch("" + (char)0x0D + (char)0x0A + "  ", tester, 2, 2);
        Assertion.assertMatch(";        " + (char)0x0D + (char)0x0A + " ", tester, 2, 2);
        Assertion.assertMatch(";AbCd123\"" + (char)0x0D + (char)0x0A + " ", tester, 2, 2);
        Assertion.assertMatch(";        " + (char)0x0D + (char)0x0A + " " + (char)0x0D + (char)0x0A, tester, 2, 2);
    }


//    comment        =  ";" *(WSP / VCHAR) CRLF
	protected String comment() throws IOException, MatchException {
        String comment = "";
//      註釋是分號開頭
        assertMatch(is.peek(), ';');
        int value = is.read();
        comment += (char)value;

//      如果下一個字符是0x20, 0x09,或者0x21-0x7E之間,則進入循環
//      直至輸入字符不再這個範圍之內。
//      循環內是一個解析WSP或者VCHAR的過程,WSP和VCHAR的FIRST交集爲空,
//      因而是可以通過向前看一個字符區分開來的。
//      另外WSP/VCHAR允許0個或任意多個,所以此處使用while是可以的。
        while (match(is.peek(), 0x20) || match(is.peek(), 0x09) || match(is.peek(), 0x21, 0x7E)) {
            if (match(is.peek(), 0x20) || match(is.peek(), 0x09)) comment += WSP();
            else comment += VCHAR();
//			if (peekMatch ==0x20 || peekMatch == 0x09) WSP();
//			else if (peekMatch >= 0x21 && peekMatch <= 0x7E) VCHAR();
		}
//      結束之前要匹配回車換行字符
		comment += CRLF();
        return comment;
	}

    //  VCHAR          =  %x21-7E
    //    comment        =  ";" *(WSP / VCHAR) CRLF
    @Test
    public void testComment() throws Exception {
        Tester<String> tester = new Tester() {
            public String test(AbnfParser parser) throws MatchException, IOException {
                return parser.comment();
            }
        };
        Assertion.assertMatch(";" + (char)0x0D + (char)0x0A, tester, 1, 2);
        Assertion.assertMatch(";" + (char)0x7E + (char)0x0D + (char)0x0A, tester, 1, 2);
        Assertion.assertMatch(";" + "   " + (char)0x0D + (char)0x0A, tester, 1, 2);
        Assertion.assertMatchException(";", tester, 2, 1);
        Assertion.assertMatchException(" ", tester, 1, 1);
//      對於這種情形,和前面的c_wsp()的問題是類似的。
        Assertion.assertMatchException(";" + (char) 0x0D, tester, 1, 1);
    }

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

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