在沉默了数月之后,博主心血来潮想继续介绍QParserGenerator,在这里我们将不再继续介绍任何有关于LALR(1)的算法(那东西只会把你的脑子变成一团浆糊),让我们来看一下QParserGenerator的具体用法。

说到ParserGenerator不得不提的是BNF,应此QParserGenerator也有它自己的BNF,这时有人会问BNF究竟是什么呢?简单的说BNF就是用来描述一种语法的东西,比如在Basic中If后面跟表达式然后是Then中间是语句块末尾必须要有End If等等的一系列描述,更专业的解释我们可以看一下维基百科上的解释。

好了,说完了BNF那让我们来看一下QParserGenerator的BNF到底是长啥样的



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->%token "%" "token" "start" "|" "-" ">" ";" "[" "]";

%start start;

strings             -> strings "{String}"
                    |  "{String}"
                    ;

vs                  -> vs "{Letter}"
                    |  vs "{String}"
                    |  "{Letter}"
                    |  "{String}"
                    ;

option              -> "[" vs "]"
                    ;

oneProductionRight  -> oneProductionRight option
                    |  oneProductionRight vs
                    |  option
                    |  vs
                    ;

someProductionRight -> someProductionRight "|" oneProductionRight
                    |  oneProductionRight
                    ;

token               -> "%" "token" strings ";"
                    ;

someTokens          -> someTokens token
                    |  token
                    ;

production          -> "{Letter}" "-" ">" someProductionRight ";"
                    ;

someProductions     -> someProductions production
                    |  production
                    ;

start               -> someTokens "%" "start" "{Letter}" ";" someProductions
                    |  "%" "start" "{Letter}" ";" someProductions
                    ;

也许有人会问,不对啊根据维基百科上的说明BNF不应该是长这样的,其实QParserGenerator是一个BNF的生成器,它可以将输入的BNF通过一系列的运算最后生成LALR(1)分析表,为了BNF文件的美观和方便处理我特地把他设计成了这个样子的而已,好了下面我们就以这个BNF文件来说明应该如何来书写BNF文件。

首先可以看到最顶上有一些以%token开头的字符串(在C语言中我们将用双引号括起来的字符序列称为字符串)以及最后的一个分号,其实这里的这些字符串正是BNF中说说的终结符,所以我们规定,所有其他没用%token声明的符号都是非终结符。终结符是用来做移进操作的,在某种特定的语言中他表现为一个token,而非终结符可以理解为一个代词,通常一个非终结符都可以展开为一条或多条规则(产生式)。至于说为什么每条内容后面都会有分号呢,只是为了处理上的方便(消除语法上的冲突?)。
好了,我们把终结符和非终结符这两个专业术语给解释完了,接下来可以看到的是一个以%start开头后跟一个非终结符的语句,他表明了所有规则(产生式)是从哪里开始的(有始无终的节奏-_-||杯具啊)。

最后就是我们的重头了,多空一行也不为过吧。这里有一大堆的产生式,那我们如何来阅读他呢,其实上面已经介绍了有个表明了所有规则开头的非终结符,好那让我们来找一下他所对应的产生式在哪里



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->start               -> someTokens "%" "start" "{Letter}" ";" someProductions
                    |  "%" "start" "{Letter}" ";" someProductions
                    ;

可以看到所有的规则可分为左半部分和右半部分,左边总是一个非终结符来说明他应该被哪一些规则来替代,而右边则是这些规则的具体内容包含了一些终结符和非终结符序列,中间则用一个箭头符号来分割。在所有的规则中非终结符都是不带引号的,而终结符都是用引号将其括起来的,在终结符中有一些内置的变量来表达一些特定的表达式,这个会在下文中做出说明。当然对于同一个终结符来说我们可以用任意多个规则来说明他,他们都是或的关系,由于BNF中不可能存在且的关系,应此我们并不需要考虑他。

下面让我们来看一下预定义的终结符有哪些,从Parser.cpp的代码中可知预定义的终结符有"{String}"、"{Digit}"、"{Real}"、"{Letter}"。
"{String}":表示正则表达式\"[^\"]*\"
"{Digit}":表示正则表达式[0-9]+
"{Real}":表示正则表达式[0-9]*.[0-9]+
"{Letter}":表示正则表达式((_[0-9]+)|([_a-zA-Z]+))[_0-9a-zA-Z]*
从这些正则表达式中可见"{String}"表示一个带双引号的字符串,"{Digit}"则表示一个数字,"{Real}"则表示一个浮点数,"{Letter}"则表示一个不带双引号的字符串。当然这些正则表达式写的并不完备,比如"{String}"中没有支持转义等等。

然后让我们来看一下每条规则支持哪些语法,首先从下面几条文法中可知,可用方括号将一些可选项括起来。



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> vs                  -> vs "{Letter}"
                     |  vs "{String}"
                     |  "{Letter}"
                     |  "{String}"
                     ;
 
 option              -> "[" vs "]"
                     ;

而对于一个规则来说他可以用若干条产生式来说明他,其中每条产生式之间是或的关系。



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> oneProductionRight  -> oneProductionRight option
                     |  oneProductionRight vs
                     |  option
                     |  vs
                     ;
 
 someProductionRight -> someProductionRight "|" oneProductionRight
                     |  oneProductionRight
                     ;

其他一些规则则说明了一些上文提到的规则,比如开头是一些token的定义等。终于把QParserGenerator的文法文件的结构给介绍完了,在接下来的一篇文章中我们将介绍如何用QParserGenerator来生成一个带括号优先级的四则混合运算计算器,其文法可见Calculator.txt,QLanguage整个项目的代码可见https://github.com/lwch/QLanguage/

QParserGenerator的文法文件介绍的更多相关文章

  1. Linux core 文件介绍

    Linux core 文件介绍 http://www.cnblogs.com/dongzhiquan/archive/2012/01/20/2328355.html 1. core文件的简单介绍在一个 ...

  2. linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

    原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...

  3. Android下HelloWorld项目的R.java文件介绍

    R.java文件介绍 HelloWorld工程中的R.java文件 package com.android.hellworld; public final class R {     public s ...

  4. APK扩展文件介绍、功能及用法

    APK扩展文件介绍 Android Market (Google Play Store)中每一个APK文件的最大限制是50MB.假设您的程序中包括大量的数据文件,曾经您仅仅能把这些数据文件放到自己的s ...

  5. NSIS文字及字符串函数与头文件介绍

    原文 NSIS文字及字符串函数与头文件介绍 文字函数,顾名思义就是处理字符串的函数.使用这些字符串函数前,必须先包含头文件WordFunc.nsh.该头文件目前包含如下一些函数:WordFind.Wo ...

  6. opensslBIO系列之2---BIO结构和BIO相关文件介绍

    BIO结构和BIO相关文件介绍     (作者:DragonKing Mail:wzhah@263.net 公布于:http://gdwzh.126.com openssl专业论坛)          ...

  7. 微信小程序-01-项目组成文件介绍(入门篇)

    自古开篇先说两句,写这些笔记不是学习用的,主要是后续分享一些遇到的坑,碰到过什么样的问题,怎么去解决,如果你不是一个很耐心无看文章的人,建议去 网易云课堂找一些课程,跟着别人的脚步或许会更有动力,我的 ...

  8. IOS-项目中常见文件介绍

    一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要用来放依赖的框架 3.test文件夹是 ...

  9. Linux文件介绍

    Linux文件介绍 Linux 文件属性 可以通过命令ll+文件名,查看文件的具体属性 例如:ll syz.gz 1736706 -rw-r--r--. 1 root root 28 Oct 27 1 ...

随机推荐

  1. [译]:Xamarin.Android开发入门——Hello,Android深入理解

    返回索引目录 原文链接:Hello, Android_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android深入理解 本部分介绍利用Xamarin开发And ...

  2. win10控制台程序printf死锁问题

    昨天遇到一个奇葩的问题,服务器正常运行但经常出现客户端无法连接的问题.我很好奇,在accept返回的地方断点,发现无法accept了.这就怪了,以前从没出现过这种情况.服务器网络用的asio,无法ac ...

  3. 【转】SSL协议、SET协议、HTTPS简介

    一.SSL协议简介 SSL是Secure Socket Layer的缩写,中文名为安全套接层协议层.使用该协议后,您提交的所有数据会首先加密后,再提交到网易邮箱,从而可以有效防止黑客盗取您的用户名.密 ...

  4. tomcat发布脚本

    #!/bin/bash #发布相关目录Tomcat_log='/home/CodePub/tomcatlog'dev_package='/home/CodePub/package'old_packag ...

  5. C#中的null与void

    一.null: 1.明义,null是什么意思? null是指一个变量没有指向具体对象的有效引用. 这句话什么意思呢?意思就是 1).能够使用null修饰的是变量: 2).主要指的是引用. 那么这就引出 ...

  6. 整理ViewController的生命周期和加载过程

    按照执行顺序排列 - initWithCoder:通过nib文件初始化时触发 - awakeFromNib:nib文件被加载的时候,会发送一个awakeFromNib的消息到nib文件中的每个对象 p ...

  7. CSS 一些知识点

  8. php和ajax 服务器端做轮询推送(定义)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  9. iOS地图

    地图 1.主要用到了地图展示和定位功能 CoreLocation框架的使用: 导入头文件        #import <CoreLocation/CoreLocation.h>CoreL ...

  10. gulp-less解决遇到错误停止执行task

    来龙去脉 在用less+gulp开发时,有时候代码还没写完整,不小心保存了一下,然后gulp就开始执行gulp-less的task. 但是代码是有问题的,这时候会输出一个Potentially unh ...