从网上无意间看到这个系列的文章,作者非常有想法,转下来慢慢研究,好好学习。   祝大家学习愉快,做自己的爱好 ^_^ !

  上一篇文章中我们看到了可配置语法分析器使用起来的样子,在这篇文章中我将告诉大家如何通过重载操作符的方法构造文法表达式树,从而使用递归向下法进行语法分析的工作。

在这之前我们将研究一下什么是文法表达式。我们将文法表达式看成分析器,于是复杂的文法表达式就是由简单的分析器通过各种方法组合起来的复杂分析器。一个分析器有以下几个属性:

1:输入类型。输入类型通常是一个字符串的指针还是迭代器什么的,具体类型不重要,重要的是输入状态必须能被复制,能跳到下一个元素。当然wchar_t*也满足这种要求,但是我们为了通用性(譬如可以为你自己的容器扩展出一个输入迭代器)我们采用类似STL的迭代器的方法,也就是concept(这并没有包含其技巧,只是概念)来实现。然后库将为一些基本的东西提供默认的迭代器,譬如IEnumerable<T>(嗯嗯,这不是C#,已经被Vczh Library++实现了。容器采用了一种泛型+接口的方法,但是在不必要的情况下允许不支付虚函数的代价,不过这根本章内容无关,以后再谈),或者WString和AString。

2:输出类型。输出类型一般包含两个方面。第一个是成功后的结果,第二个是失败后的错误信息。怎么让可配置语法分析器在恰当的地方输出类型也是一个很复杂的问题,不过这根本章内容无关,下一篇文章接着讲这个细节。在这里我们先忽略错误信息,就如同正则表达式拒绝匹配一个字符串也不会告诉你为什么一样。

我们可以通过这两种属性来构造出一个文法表达式的基类。表达式树通常用基类+若干子类的方法来实现,有了基类等于定下了子类的基调。

1 template<typename I, typename O>
2 class Expression
3 {
4 public:
5   virtual Maybe<O> Parse(I& input)=0;
6 };

Maybe指的是里面可以有类型O的值,或者什么都没有。这额外的信息可以添加一个bool来表达,这里就不赘叙了。到了这里我们明白一个表达式树的重点不是其内容,而是分析输入的算法。因此我们可以组合出连接、分支和循环:

 1 template<typename I, typename O1, typename O2>
 2 class Sequence : public Expression<I, ParsingPair<O1, O2>>;
 3 {
 4 public:
 5   Ptr<Expression<I, O1>> left;
 6   Ptr<Expression<I, O2>> right;
 7 
 8   Maybe<ParsingPair<O1, O2>> Parse(I& input);
 9 };
10 
11 template<typename I, typename O>
12 class Alternate : public Expression<I, O>;
13 {
14 public:
15   Ptr<Expression<I, O>> left;
16   Ptr<Expression<I, O>> right;
17 
18   Maybe<O> Parse(I& input);
19 };
20 
21 template<typename I, typename O>
22 class Loop : public Expression<I, ParsingList<O>>;
23 {
24 public:
25   Ptr<Expression<I, O>> element;
26   int min;
27   int max;
28 
29   Maybe<ParsingList<O>> Parse(I& input);
30 };

这就是连接、分支和循环的声明了。现在我们可以很清楚的了解什么是带类型的文法了。类型主要指的是输出类型,而输入类型肯定是不能变化的。ParsingPair<A, B>就是一个带两个数据的结构,而ParsingList<T>是一个链表。做成这样主要是为了在传递他们的时候不要做太多浪费的复制工作,在这里我们只需要了解其概念就好了。

每一种组合都对子文法的类型有着一些要求,譬如说分支要求左右文法表达式的类型是一样的。而且输出类型是通过子文法的类型计算而得到的。Ptr<T>是智能指针,在这里使用主要是为了避免复制的时候出现问题。智能指针在这种数据结构下还是十分好用的,反正构造和析构一条文法的效率都是无关紧要的,不要太慢就可以了。

但是我们如何重载操作符来组合文法表达式呢?其实文法表达式最终产生的结果都是Ptr<Expression<I, O>>,Ptr的操作符重载是不能修改的,所以我们还要一个代理类:

 1 template<typename I, typename O>
 2 class Node
 3 {
 4 public:
 5   Ptr<Expression<I, O>> expression;
 6 };
 7 
 8 template<typename I, typename O>
 9 Node<I, O> operator|(const Node<I, O>& left, const Node<I, O>& right);
10 
11 template<typename I, typename O1, typename O2>
12 Node<I, ParsingPair<O1, O2>> operator+(const Node<I, O1>& left, const Node<I, O2>& right);
13 
14 //除了+以外,还可以继承*啊,或者干脆写个loop(node, min, max)什么的
15 template<typename I, typename O>
16 Node<I, ParsingList<O>> operator+(const Node<I, O>& element);

我们就可以在每一个操作符重载里面将各自Node的expression成员变量拿出来,然后通过构造上面提供的Sequence、Alternate和Loop来构造更加复杂的文法表达式,最后重新装进一个Node<I, O>里面就行了。

这就是我们可以将文法写进C++的小技巧。下一篇文章我们将会了解到表达式的每一个Parse函数内部都做了些什么。

转载于:https://www.cnblogs.com/xuangong/archive/2011/07/31/2122662.html

【转】Vczh Library++ 3.0之可配置语法分析器(设计文法表达式)相关推荐

  1. 【转】Vczh Library++3.0之可配置语法分析器(前言)

    从网上无意间看到这个系列的文章,作者非常有想法,转下来慢慢研究,好好学习. 祝大家学习愉快,做自己的爱好 ^_^ ! 花了差不多两个星期的时间将一个可配置语法分析器(Combinator)写好了.这个 ...

  2. Vczh Library++3.0 开源啦!

    项目主页:http://vlpp.codeplex.com/ Vczh Library++从2006年就开始开发,到现在经历了一些版本变迁,到现在已经正式步入3.0了.现在Vczh Library++ ...

  3. Vczh Library++3.0之正则表达式引擎(生成epsilon-NFA)

    从正则表达式生成epsilon-NFA其实跟将一棵树变换成另一棵树是类似的.epsilon转换提供了一种工具让我们可以把一个图表达成漂亮的形式,看起来就有典型的递归结构.因此这个工作依然可以用Rege ...

  4. C++轻量级可配置语法分析器(开源) - λ-calculus(惊愕到手了欧耶,GetBlogPostIds.aspx) - C++博客...

    C++轻量级可配置语法分析器(开源) - λ-calculus(惊愕到手了欧耶,GetBlogPostIds.aspx) - C++博客 C++轻量级可配置语法分析器(开源) - λ-calculus ...

  5. Vczh Library++3.0实现二进制模板函数

    现在NativeX已经支持跟C#一样的模板函数了:可以被编译进独立的二进制文件,然后另外一个代码引用该二进制文件,还能实例化新的模板函数.现在先来看debug log输出的二进制结构.首先是被编译的代 ...

  6. Vczh Library++ 语法分析器开发指南

    Vczh Library++ 语法分析器开发指南 陈梓瀚 前言 在日常的开发工作中我们总是时不时需要写一些语法分析器.语法分析器不一定指的是一门语言的编译器前端,也有可能仅仅是一个自己设计格式的配置文 ...

  7. 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级) 本章介绍的是企业库加密应用程序模块 ...

  8. Enterprise Library 2.0 技巧(3):记录ASP.NET站点中未处理的异常

    这篇文章不能算是Enterprise Library 2.0的一个技巧,只是Logging Application Block的一个简单应用而已,在这里我们使用Logging Application ...

  9. Enterprise Library 3.0 体验(3):使用配置文件的Validation Application Block

    摘要:Enterprise Library 3.0 January 2007 CTP版发布了,这次发布的版对于Validation Application Block有了很大的改进,包括对配置工具的支 ...

最新文章

  1. 数据转数字类型的方法总结
  2. 第二模块_找钱:融资与管理_1
  3. Linux运维架构师、SRE技术图谱
  4. android用IO实现日记的读写,android开发实现文件读写
  5. 炒股的最终下场(搞笑趣图)
  6. redhat 完全卸载mysql_Linux完全卸载MySQL
  7. Google 展示广告
  8. unity步步生花(触发类互动)
  9. 25个关于excel工作表的操作
  10. 北京公积金贷款不够用 提升额度或有利刚需购房
  11. python通过pyautogui库来控制鼠标和键盘
  12. 局域网资产发现过程(利用工具nmap、masscan)
  13. 大话赛宁云 | 培训服务打造实战型网络安全人才
  14. 打怪小游戏(已支持商店)
  15. win10配置Java环境
  16. 常见电路结构分析四:plc控制系统与其他控制系统的比较
  17. asp读取QQwry.dat
  18. 江民在线杀毒充值的痛苦经历
  19. D - Vessels(堆优化模拟)
  20. ospf路由概念简述(入门)

热门文章

  1. “Hello World!”团队第六周的第二次会议
  2. 一道概率题:重男轻女的情况下家庭女孩数量的问题
  3. 互联网概述及互联网接入方法(3)
  4. ⑨电子产品拆解分析-触摸化妆镜
  5. 我的世界命令计算机,我的世界电脑版作弊大指令大全。
  6. 数据结构c/c++ 头插法尾插法建立带头结点的单链表,以数组创建带头结点的单链表和不带头结点的单链表,输出打印单链表
  7. 最新 Arduino 驱动 12接口/户外 LED显示屏/LED点阵屏/LED单元板
  8. Educode--故宫壁纸网页图片的爬取实验
  9. 明星热图|宋轶、辛芷蕾、王丽坤等演绎服饰新品;肖战代言李宁;林俊杰献唱迪士尼经典歌曲...
  10. 如何让公司变得更美好