基于Predictive Parsing的ABNF语法分析器(十一)——AbnfParser文法解析器之重复文法(repetition)

使用 Python 开发一个 Python 解释器 t.value = int(t.value)return tdef t_error(t):print(f"keyword not found: {t.value[0]}\nline {t.lineno}")t.lexer.skip(1)def t_newline(t):r"“”\n+“”"t.lexer.lineno += t.value.count(“\n”)为导入词法分析器,我们将使用:import ply.lex as lext_ 是一个特殊的前缀,表示定义标记的规则。每条词法规则都是用正则表达式制作 阅读详情

今天写的是关于重复文法的解析,ABNF和BNF相比,一个明显的差异就是引入了重复语法,使得我们可以方便的让一个文法元素重复若干次。

例如30"B"表示30个字母B,30*60表示最少30个,最多60个字母B,等等。

先来看看解析部分的代码:

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

//		        repetition     =  [repeat] element
//    DIGIT          =  %x30-39
	protected Repetition repetition() throws IOException, MatchException {
		Repeat repeat = null;
//      若以数字或者星号开头,则进入repeat
        if (match(is.peek(), 0x30, 0x39) || match(is.peek(), '*')) {
			repeat = repeat();
		}
//      element是必须的
		Element element = element();
		return new Repetition(repeat, element);
	}

//		        repeat         =  1*DIGIT / (*DIGIT "*" *DIGIT)
	protected Repeat repeat() throws IOException, MatchException {
		int min = 0, max = 0;
//      如果repeat是以星号开头,则重复的最小次数为0次,即repeat后面的element可以不出现。
        if (match(is.peek(), '*')) {
            is.read();
//          如果星号后面有数字,则重复的最大次数是该数字所表示的次数,否则最大次数没有限制
            if (match(is.peek(), 0x30, 0x39)) {
                while (match(is.peek(), 0x30, 0x39)) {
                    max = max * 10 + Integer.valueOf(String.valueOf((char)is.read()));
                }
            }
            return new Repeat(min, max);
        } else if (match(is.peek(), 0x30, 0x39)) {
//      repeat是以数字开头,其值表示重复的最小次数
			while (match(is.peek(), 0x30, 0x39)) {
				min = min * 10 + Integer.valueOf(String.valueOf((char)is.read()));
			}
//          如果有星号,则表示有范围
            if (match(is.peek(), '*')) {
                is.read();
//              星号后面接着数字,表示重复的最大次数,否则最大次数没有限制
                if (match(is.peek(), 0x30, 0x39)) {
                    while (match(is.peek(), 0x30, 0x39)) {
                        max = max * 10 + Integer.valueOf(String.valueOf((char)is.read()));
                    }
                }
                return new Repeat(min, max);
            } else {
//          没有星号,表示固定的重复次数
                return new Repeat(min, min);
            }
		} else {
            throw new MatchException("['0'-'9', '*']", 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/>.
 */

    //		        repeat         =  1*DIGIT / (*DIGIT "*" *DIGIT)
    @Test
    public void testRepeat() throws Exception {
        Tester<Repeat> tester = new Tester<Repeat>() {
            @Override
            public Repeat test(AbnfParser parser) throws MatchException, IOException {
                return parser.repeat();
            }
        };

        String input;
        Assert.assertEquals(new Repeat(0,0), AbnfParserFactory.newInstance("*").repeat());
        Assert.assertEquals(new Repeat(0,0), AbnfParserFactory.newInstance("**").repeat());
        Assert.assertEquals(new Repeat(0,0), AbnfParserFactory.newInstance("*C").repeat());
        Assert.assertEquals(new Repeat(1,1), AbnfParserFactory.newInstance("1").repeat());
        Assert.assertEquals(new Repeat(1,1), AbnfParserFactory.newInstance("1M").repeat());
        Assert.assertEquals(new Repeat(2,0), AbnfParserFactory.newInstance("2*").repeat());
        Assert.assertEquals(new Repeat(2,0), AbnfParserFactory.newInstance("2*_").repeat());
        Assert.assertEquals(new Repeat(0,3), AbnfParserFactory.newInstance("*3").repeat());
        Assert.assertEquals(new Repeat(0,3), AbnfParserFactory.newInstance("*3").repeat());
        Assert.assertEquals(new Repeat(0,3), AbnfParserFactory.newInstance("*3J").repeat());
        Assert.assertEquals(new Repeat(4,9), AbnfParserFactory.newInstance("4*9").repeat());
        Assert.assertEquals(new Repeat(4,9), AbnfParserFactory.newInstance("4*9#").repeat());
        Assert.assertEquals(new Repeat(5,0), AbnfParserFactory.newInstance("5**").repeat());
        Assert.assertEquals(new Repeat(6, 0), AbnfParserFactory.newInstance("6*B").repeat());
        Assertion.assertMatchException("", tester, 1, 1);
        Assertion.assertMatchException("#", tester, 1, 1);
    }

    //		        element        =  rulename / group / option /
//		                          char-val / num-val / prose-val
    //		        repetition     =  [repeat] element
//    DIGIT          =  %x30-39
    @Test
    public void testRepetition() throws Exception {
        Tester<Repetition> tester = new Tester<Repetition>() {
            @Override
            public Repetition test(AbnfParser parser) throws MatchException, IOException {
                return parser.repetition();
            }
        };
        Assertion.assertMatch(
                "B", tester,
                new Repetition(new RuleName("", "B")),
                2, 1);
        Assertion.assertMatch("1B", tester,
                new Repetition(new Repeat(1, 1), new RuleName("", "B")),
                3, 1);
        Assertion.assertMatch("2*6B", tester,
                new Repetition(new Repeat(2, 6), new RuleName("", "B")),
                5, 1);

        Assertion.assertMatch("3*B", tester,
                new Repetition(new Repeat(3, 0), new RuleName("", "B")),
                4, 1);

        Assertion.assertMatch("*8B", tester,
                new Repetition(new Repeat(0, 8), new RuleName("", "B")),
                4, 1);

        Assertion.assertMatch("*B", tester,
                new Repetition(new Repeat(0, 0), new RuleName("", "B")),
                3, 1);


        Option option = AbnfParserFactory.newInstance("[B]").option();

        Assertion.assertMatch(
                "[B]", tester,
                new Repetition(option),
                4, 1);
        Assertion.assertMatch("1[B]", tester,
                new Repetition(new Repeat(1, 1), option),
                5, 1);
        Assertion.assertMatch("2*6[B]", tester,
                new Repetition(new Repeat(2, 6), option),
                7, 1);

        Assertion.assertMatch("3*[B]", tester,
                new Repetition(new Repeat(3, 0), option),
                6, 1);

        Assertion.assertMatch("*8[B]", tester,
                new Repetition(new Repeat(0, 8), option),
                6, 1);

        Assertion.assertMatch("*[B]", tester,
                new Repetition(new Repeat(0, 0), option),
                5, 1);


        Group group = AbnfParserFactory.newInstance("(B)").group();

        Assertion.assertMatch(
                "(B)", tester,
                new Repetition(group),
                4, 1);
        Assertion.assertMatch("1(B)", tester,
                new Repetition(new Repeat(1, 1), group),
                5, 1);
        Assertion.assertMatch("2*6(B)", tester,
                new Repetition(new Repeat(2, 6), group),
                7, 1);

        Assertion.assertMatch("3*(B)", tester,
                new Repetition(new Repeat(3, 0), group),
                6, 1);

        Assertion.assertMatch("*8(B)", tester,
                new Repetition(new Repeat(0, 8), group),
                6, 1);

        Assertion.assertMatch("*(B)", tester,
                new Repetition(new Repeat(0, 0), group),
                5, 1);


        CharVal charVal = AbnfParserFactory.newInstance("\"ABC\"").char_val();

        Assertion.assertMatch(
                "\"ABC\"", tester,
                new Repetition(charVal),
                6, 1);
        Assertion.assertMatch("1\"ABC\"", tester,
                new Repetition(new Repeat(1, 1), charVal),
                7, 1);
        Assertion.assertMatch("2*6\"ABC\"", tester,
                new Repetition(new Repeat(2, 6), charVal),
                9, 1);

        Assertion.assertMatch("3*\"ABC\"", tester,
                new Repetition(new Repeat(3, 0), charVal),
                8, 1);

        Assertion.assertMatch("*8\"ABC\"", tester,
                new Repetition(new Repeat(0, 8), charVal),
                8, 1);

        Assertion.assertMatch("*\"ABC\"", tester,
                new Repetition(new Repeat(0, 0), charVal),
                7, 1);


        Element numVal = AbnfParserFactory.newInstance("%x00-FF").num_val();

        Assertion.assertMatch(
                "%x00-FF", tester,
                new Repetition(numVal),
                8, 1);
        Assertion.assertMatch("1%x00-FF", tester,
                new Repetition(new Repeat(1, 1), numVal),
                9, 1);
        Assertion.assertMatch("2*6%x00-FF", tester,
                new Repetition(new Repeat(2, 6), numVal),
                11, 1);

        Assertion.assertMatch("3*%x00-FF", tester,
                new Repetition(new Repeat(3, 0), numVal),
                10, 1);

        Assertion.assertMatch("*8%x00-FF", tester,
                new Repetition(new Repeat(0, 8), numVal),
                10, 1);

        Assertion.assertMatch("*%x00-FF", tester,
                new Repetition(new Repeat(0, 0), numVal),
                9, 1);

        ProseVal proseVal = AbnfParserFactory.newInstance("<ABC>").prose_val();

        Assertion.assertMatch(
                "<ABC>", tester,
                new Repetition(proseVal),
                6, 1);

        Assertion.assertMatch("1<ABC>", tester,
                new Repetition(new Repeat(1, 1), proseVal),
                7, 1);

        Assertion.assertMatch("2*6<ABC>", tester,
                new Repetition(new Repeat(2, 6), proseVal),
                9, 1);

        Assertion.assertMatch("3*<ABC>", tester,
                new Repetition(new Repeat(3, 0), proseVal),
                8, 1);

        Assertion.assertMatch("*8<ABC>", tester,
                new Repetition(new Repeat(0, 8), proseVal),
                8, 1);

        Assertion.assertMatch("*<ABC>", tester,
                new Repetition(new Repeat(0, 0), proseVal),
                7, 1);


        Assertion.assertMatchException("**", tester, 2, 1);
        Assertion.assertMatchException("1", tester, 2, 1);
        Assertion.assertMatchException("*1", tester, 3, 1);
        Assertion.assertMatchException("*(", tester, 3, 1);
        Assertion.assertMatchException("*[", tester, 3, 1);
        Assertion.assertMatchException("1*", tester, 3, 1);
        Assertion.assertMatchException(".", tester, 1, 1);

    }



【游戏编程扯淡精粹】解析器实现模式 【游戏编程扯淡精粹】解析器实现模式 2020年1月7日 我已经写了几个parser了,parser是有标准实现模式,以及测试方法 如何解析一门语言? 在开始动手之前: 先简单学习这门语言 然后获取语言的ANTLR语法,没有的话可以参考BNF自己翻译成ANTLR语法 输入之前学习时的语言代码到ANTLR来查看AST,相当于测试语法,确保自己写的语法正确 这个过程需要熟悉语法规格(syntax specification),对语义有一个初步认识 Lexer做什么 lexer也就是一个tokenizer,将原 阅读详情

相关推荐

基于Predictive ParsingABNF语法分析器(一)——ABNF语法介绍

最近一直在做Session Initiation Protocol (SIP)协议方面的开发,SIP在电信VoIP领域应用非常广泛,是一个基于文本语法的协议。SIP语法规范是使用ABNF来定义的。对SIP语法有兴趣的同学请移步其Augmented BNF for the SIP Protocol章节。Augmented BNF for Syntax Specifications: ABNF

码农的理想国 3790

ABNF语法开发指南_讯飞ABNF语法开发指南.chm_

讯飞ABNF语法开发指南.chm,便于使用讯飞平台进行开发

别再死记硬背了!ROS开发者必备:rosbag record/play/info 高频命令速查手册

本文为ROS开发者提供rosbag record/play/info命令的高效使用手册,涵盖智能录制、元数据分析、精准回放等进阶技巧,帮助开发者提升机器人数据记录与分析效率。通过实战案例和参数优化建议,解决高频数据捕获、时间同步等常见问题,释放rosbag作为数据记录工具的全部潜力。

weixin_30516243的博客 1086

BBT BNF Parser - 基于BNF的通用解析器

这是一个通用的文本解析器. 他的使用类似于正则表达式, 但比正则表达式更复杂, 可以用来解析更复杂的文本. 所谓"通用", 指的是只要你能用BNF按照一定的规则正确的将你要解析的内容描述出来, 那么就可以使用这个解析器来解析对应的文本.举个例子说, 我现在想要解析MS SQL Server所使用的TSQL语言定义的查询语句, 那么比较直接的办法就是找来MSDN, 研究其中的SQL各种State

bbtsoft的专栏 2309

一个非常好的ABNF免费解析器

记下来,以后留做它用: http://www.goldparser.org/index.htm 维基百科关于BNF的介绍和相关链接: http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form 另外一个BNF解析器: http://bnfparser2.sourceforge.net/download.html

娃娃鱼的专栏 1095

谈谈Parser

一直很了解人们对于parser的误解,可是一直都提不起兴趣来阐述对它的观点。然而我觉得是有必要解释一下这个问题的时候了。我感觉得到大部分人对于parser的误解之深,再不澄清一下,恐怕这些谬误就要写进歪曲的历史教科书,到时候就没有人知道真相了。 什么是Parser首先来科普一下。所谓parser,一般是指把某种格式的文本(字符串)转换成某种数据结构的过程。最常见的parser,是把程序文本转换成编

00的专栏 1956

深入浅出数据库 parser

本文将主要讨论 SQL 是如果被解析成抽象语法树的。简单来说,就是如何将 SQL 字符串如果解析成相应数据库语言的结构体。

MatrixOrigin的博客 785

编译原理五:语法分析

上下文无关文法(Context-Free Grammar,CFG)是一种形式语言,它可以用于描述一类特定的语言结构。CFG 的一个典型应用是在编译器中,用于描述编程语言的语法规则。在 CFG 中,一个非终结符号可以被表示为一组产生式,每个产生式由一个非终结符号和若干个终结符号组成。终结符号非终结符号产生式和开始符号。终结符号是 CFG 中的最基本元素,它表示语言中的一个基本单元,如数字、标识符、运算符等。非终结符号表示语言中的一个复合单元,它可以由一个或多个终结符号或其他非终结符号组成。

to_the_Future的博客 6579

ABNF parser generator

我在做一个H248协议的模拟器,首先要做的第一步工作是将H248消息解析出来。我在搜寻一种能够根据ABNF规范自动产生Parser代码的工具。网上有一个叫做APG的工具(http://www.coasttocoastresearch.com/),但是我输入H248协议的ABNF规范还是有错误,它给出的错误消息也很难看懂。不知道parser应该怎么写?用lex/yacc?这方面的知识很欠缺,需要好好

AlexJiangJun的专栏 2012

科大讯飞ABNF文法规范

科大讯飞ABNF文法规范

ABNFBNF 文法规范和开发指南

包含 ABNF语法开发指南 、sample.abnfabnf详细的文法规范

ABNF语法开发指南

Android集成语音开发时用到科大讯飞的SDK,当使用语法识别功能时,云端识别需要使用ABNF构建识别语法

基于Predictive ParsingABNF语法分析器(十)——AbnfParser文法解析器之数值类型(num-val)

ANBF语法中的数值类型有3种:二进制、十进制和十六进制,可以是一个以点号分隔的数列,也可以是一个数值的范围。例如,%d11.22.33.44.55表示五个有次序的十进制数字“11、22、33、44、55”,而%x80-ff表示一个字节,这个字节的数值可以是在0x80至0xff之间。 我把以点号分隔的数列定义为NumVal,把范围类型的数值定义为RangedNumVal。这两个类实现了Eleme

码农的理想国 1658

语法规范:BNFABNF

早上做智能施法项目,说一句话比如“明天6点开灯”,智能插座就会在6点把灯开起来,这涉及到语音语法方面的问题。由于科大讯飞开发语义,就决定用讯飞的SDK BNF        巴科斯范式(BNF: Backus-Naur Form 的缩写)是由 John Backus 和 Peter Naur 首先引入的用来描述计算机语言语法的符号集。现在,几乎每一位新编程语言书籍的作者都使用巴科斯范式来定

棺材深處 8695

基于Predictive ParsingABNF语法分析器(六)——AbnfParser文法解析器之多个符号连接的情形(如rule和CRLF)

基于预测的文法分析器,一个明显的特点就是将非终结符定义为解析函数(方法),当非终结符号可以派生为其他非终结符号时,在解析函数中递归调用即可。这种方法的一个缺点,是难以处理需要回溯的情形,后面我们再详细分析。上次我们研究了诸如CR、LF、HTAB等单个字符的解析,这一篇来看看稍微复杂一点的多个符号连接的情形,包括CRLF和RULE两个符号。/* This file is one of the

码农的理想国 1564

ABNF(巴克斯范式)语法总结--根据RFC5234

ABNF是各类RFC中经常遇到的数据定义语法,在此把他的语法简单做个总结,所有内容均参照RFC5234的内容和结构。 1 规则定义 rule = definition ;comment     一条语句以回车换行结束。其中rule为规则名,大小写不敏感;definition为规则的具体定义; ';'后作为注释 2 定义字符 语法:% 有二进制,十进制,十六进制,分别表示为b

GjGsoft's Technical Blog 3971
上一篇: 基于Predictive Parsing的ABNF语法分析器(十)——AbnfParser文法解析器之数值类型(num-val)
下一篇: 基于Predictive Parsing的ABNF语法分析器(十二)——alternation、concatenation、group和option
造梦工程师
博客等级 码龄18年 71粉丝 40原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值