数据结构allocator内存池内存池V2traits,construct&destructvectorlistrbtreemap&sethashtablehash_map&hash_set算法 Read More
posted @ 2012-07-15 19:34 lwch 阅读(479) 评论(0) 推荐(0) Edit

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

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

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

%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开头后跟一个非终结符的语句,他表明了所有规则(产生式)是从哪里开始的(有始无终的节奏-_-||杯具啊)。

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

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}"中没有支持转义等等。

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

1 vs                  -> vs "{Letter}"
2                     |  vs "{String}"
3                     |  "{Letter}"
4                     |  "{String}"
5                     ;
6 
7 option              -> "[" vs "]"
8                     ;


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

1 oneProductionRight  -> oneProductionRight option
2                     |  oneProductionRight vs
3                     |  option
4                     |  vs
5                     ;
6 
7 someProductionRight -> someProductionRight "|" oneProductionRight
8                     |  oneProductionRight
9                     ;


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

posted @ 2013-10-09 11:19 lwch 阅读(1258) 评论(0) 推荐(0) Edit
其实早就想写本文了,一直想缅怀一下过去的自己。说是说5年,其实在很久之前我已经用按键游侠(一个用VBS作为引擎的东西)开始写脚本了,说起编程还需要感谢猪哥,是他将我带入了编程这一领域(可悲的是现在都找不到QQ列表中的哪位了,猪哥希望您看到这篇文章之后能联系我)。5年前,我性质匆匆的买来了一本VC6和VS2005(好像是这个版本)入门的书打算开始学习C++(目前这两本书在某个妹子手里)。然后开始了漫长的C++学习之旅,记得当时我是一边摸索着学习C++的语法,一边在写按键娃娃(值得庆幸的是目前这货居然还能搜的到),下面我们来看一段有意思的代码。 可以看到当时的我是多么的稚嫩,居然把一个功能函数.. Read More
posted @ 2013-06-17 23:24 lwch 阅读(15440) 评论(45) 推荐(17) Edit
接上一篇,首先需要修正的是在DFA生成算法中的传播部分,应该需要有个循环一直传播到不能传播为止,在多次实验中表明,有些展望符是通过第2,3,4甚至更多次传播得来的。应此,相应的make函数变成了Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> boolLALR1::make(){vector<LALR1Production>v;v.push_back(inputProductions[begin][0]);pStart=closu Read More
posted @ 2013-05-30 23:07 lwch 阅读(736) 评论(0) 推荐(0) Edit
以下所说的文法文件均为QParserGenerator的文法文件产生式我们将文法文件中形如Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->strings->strings"{String}"|"{String}";形式的式子称为产生式,它由它的左端非终结符(strings)和右端终结符和非终结符组成。非终结符:非终结符总是出现在产生式的左端,它表示这个条目是由右侧的一些终结符和非终结符推导而来的。 Read More
posted @ 2013-05-12 22:37 lwch 阅读(1215) 评论(0) 推荐(1) Edit
QCore/Library说明文档 李文超前言QCore/Library是一套类STL的类库,它在标准库的范围内删去了不常用的heap、deque等结构(至少我是不常用的)。并为一些容器提供了一些特殊的接口,比如vector中的push_back_unique、add和add_unique等。Library主要分为六部分,内存调试相关、容器、算法、正则、IO和Graphic,每个模块都有各自的分工,他们之间的耦合度极低,几乎每个模块都可以拆出来独立使用,下面来分别介绍各个模块。内存调试我们知道,在C/C++中内存相关的东西是极难控制的,在使用不当时可能造成各种错误,轻则内存泄漏,重则程序崩溃。 Read More
posted @ 2013-04-30 20:36 lwch 阅读(893) 评论(0) 推荐(0) Edit
接上一篇我们已经得到了一个完整的ε-NFA,下面来说说如何将ε-NFA转换为DFA(确定有限自动机)。DFA的状态在DFA中,某个状态对应到ε-NFA中的若干状态,应此我们将会得到下面这样的一个结构。 struct DFA_State { set<EpsilonNFA_State*> content; bool bFlag;#ifdef _DEBUG uint idx;#endif DFA_State(con... Read More
posted @ 2013-02-23 23:34 lwch 阅读(3042) 评论(0) 推荐(1) Edit
自动机关于自动机的说明,这里不不再复述,请到http://zh.wikipedia.org/wiki/自动机查看。表达式首先,我们规定表达式中只允许输入Char_Type和String_Type类型的字符。template <typename Char_Type, typename String_Type>class Rule{};ε-NFA的状态对于一个状态来说,我们并不需要知道他的任何信息在上面的代码中,为了调试方便,我为其加入了idx域,并为每个状态分配了一个唯一的ID。 struct EpsilonNFA_State {#ifdef _DEBUG ... Read More
posted @ 2013-02-15 20:33 lwch 阅读(3669) 评论(3) 推荐(1) Edit
在上一篇中我们已经实现了一个简单的内存池,可以申请更大块的内存块来减少申请小块内存块时产生的内存碎片。在本篇中,我们需要为其加入内存泄漏的检测代码,以此来检测代码编写过程中的疏忽带来的内存泄漏。(callstack的显示暂时仅支持Windows)一、内存泄漏检测首先,改写obj和block结构,在obj中加入一个域released表示这个chunk是否被释放Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1structobj2{3#ifdef Read More
posted @ 2013-01-19 20:16 lwch 阅读(1288) 评论(0) 推荐(0) Edit
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> template<typenameT1,typenameT2>inlineconstboolcompare_type(T1,T2){returnfalse;}template<>inlineconstboolcompare_type(int,int){returntrue;}template<>inlineconstboolcompare_type(floa Read More
posted @ 2012-08-25 16:14 lwch 阅读(413) 评论(0) 推荐(0) Edit
在STL中list是以双向链表的方式来存储的,应此使用给定的下标值来找到对应的节点所需的时间复杂度为O(n),相比vector直接使用原生指针会慢一些。因为是双向链表的关系,那么必然有一种结构来表示链表中的节点。Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> template<typenameT>struct__list_node{__list_node<T>*prev;__list_node<T>*ne Read More
posted @ 2012-08-09 21:23 lwch 阅读(1628) 评论(0) 推荐(0) Edit
点击右上角即可分享
微信分享提示