基於Predictive Parsing的ABNF文法分析器(七)——AbnfParser文法解析器之多個選項的情形(如WSP、c-nl和element)

來源:互聯網
上載者:User

現在來看看對於產生式有多個選項的情形,例如WSP可以是空格SP或者跳格HTAB。對於這種情況,一般是向前看一個字元,根據這個字元來選擇產生式。當然,如果兩個產生式的起始字元都一樣,那麼只向前看一個字元就不夠了,這種情況下需要向前看2個或者更多。

WSP、c-nl和element的文法解析程式:

 

/*    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/>. *///WSP            =  SP / HTABprotected String WSP() throws IOException, MatchException {//              向前看一個字元switch (is.peek()) {//              如果這個字元是0x20,則是SP(空格),調用SP()方法case 0x20: return SP();//              如果這個字元是0x09,則是HTAB(跳格),調用HTAB()方法case 0x09: return HTAB();//              否則拋出匹配異常MatchExceptiondefault: throw new MatchException("[0x20, 0x09]", is.peek(), is.getPos(), is.getLine());}}//        c-nl           =  comment / CRLFprotected String c_nl() throws IOException, MatchException {//              向前看一個字元switch (is.peek()) {//              如果是分號,則是注釋,調用comment()方法進行解析case ';': return comment();//              如果是0x0D,則是斷行符號,調用CRLF()方法進行解析case 0x0D: return CRLF();//              否則拋出異常default: throw new MatchException("[';', 0x0D]", is.peek(), is.getPos(), is.getLine());}}//        element        =  rulename / group / option ///                          char-val / num-val / prose-valprotected Element element() throws IOException, MatchException {//      向前看一個字元,如果在0x41~0x5A或0x61~0x7A之間(即大小寫英文字母),則是規則名,調用rulename()方法進行解析        if (match(is.peek(), 0x41, 0x5A) || match(is.peek(), 0x61, 0x7A)) {            return rulename();        }//      否則再檢查這個字元        switch (is.peek()) {//          如果是左括弧,則是group,調用group()            case '(': return  group();//          如果是左方括弧,則調用option()            case '[': return option();//          如果是雙引號,則調用char_var()            case 0x22: return char_val();//          如果是百分比符號,則調用num_val()            case '%': return num_val();//          如果是左角括弧(小於符號),則調用prose_val()            case '<': return prose_val();//          否則拋出匹配異常            default: throw new MatchException("['(', '[', 0x22, '%', '<']", is.peek(), is.getPos(), is.getLine());        }}

相應的單元測試代碼也不複雜,如果有不清查的地方麻煩看看前面的文章:

/*    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/>. */    //WSP            =  SP / HTAB    @Test    public void testWSP() throws Exception {        Tester<String> tester = new Tester<String>() {            @Override            public String test(AbnfParser parser) throws MatchException, IOException {                return parser.WSP();            }        };        Assert.assertEquals(String.valueOf((char)0x09), AbnfParserFactory.newInstance(new char[] {0x09}).WSP());        Assert.assertEquals(String.valueOf((char)0x20), AbnfParserFactory.newInstance(new char[] {0x20}).WSP());        Assert.assertEquals(String.valueOf((char)0x09), AbnfParserFactory.newInstance(new char[] {0x09, 0x09}).WSP());        Assert.assertEquals(String.valueOf((char)0x09), AbnfParserFactory.newInstance(new char[] {0x09, 0x20}).WSP());        Assert.assertEquals(String.valueOf((char)0x20), AbnfParserFactory.newInstance(new char[] {0x20, 0x20}).WSP());        Assert.assertEquals(String.valueOf((char)0x20), AbnfParserFactory.newInstance(new char[] {0x20, 0x09}).WSP());        Assert.assertEquals(String.valueOf((char)0x20), AbnfParserFactory.newInstance(new char[] {0x20, 0x30}).WSP());        Assertion.assertMatchException("", tester, 1, 1);        Assertion.assertMatchException("" + (char)0x08, tester, 1, 1);    }    //        c-nl           =  comment / CRLF    @Test    public void testC_nl() throws Exception {        Tester<String> tester = new Tester() {            public String test(AbnfParser parser) throws MatchException, IOException {                return parser.c_nl();            }        };        Assertion.assertMatch("" + (char)0x0D + (char)0x0A, tester, 1, 2);        Assertion.assertMatch(";" + (char)0x0D + (char)0x0A, tester, 1, 2);        Assertion.assertMatch(";" + (char)0x21 + (char)0x0D + (char)0x0A, tester, 1, 2);        Assertion.assertMatch(";" + (char)0x20 + (char)0x0D + (char)0x0A, tester, 1, 2);    }    //        element        =  rulename / group / option ///                          char-val / num-val / prose-val    @Test    public void testElement() throws Exception {        Tester<Element> tester = new Tester<Element>() {            @Override            public Element test(AbnfParser parser) throws MatchException, IOException {                return parser.element();            }        };        String input;        input = "aBcD1234";        RuleName ruleName = AbnfParserFactory.newInstance(input).rulename();        Assertion.assertMatch(input, tester, ruleName, 9, 1);        input = "(aBcD1234/%d88)";        Group group = AbnfParserFactory.newInstance(input).group();        Assertion.assertMatch(input, tester, group, 16, 1);        input = "[aBcD1234/%d88]";        Option option = AbnfParserFactory.newInstance(input).option();        Assertion.assertMatch(input, tester, option, 16, 1);        input = "\"#$%^\"";        CharVal charVal = AbnfParserFactory.newInstance(input).char_val();        Assertion.assertMatch(input, tester, charVal, 7, 1);        input = "%b0101.1010.1111";        Element numVal = AbnfParserFactory.newInstance(input).num_val();        Assertion.assertMatch(input, tester, numVal, 17, 1);        input = "<aBcD1234/%d88>";        ProseVal proseVal = AbnfParserFactory.newInstance(input).prose_val();        Assertion.assertMatch(input, tester, proseVal, 16, 1);    }

總之單元測試的目標就是想盡辦法“虐”你的代碼吧,不過我發現這些代碼真的經不起虐。。。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.