TPL文法(2): 标记、动作与约束(Mark, Action and Restriction)

引言

有了对《TPL基础文法》的了解后,你就可以用TPL去做些事情了。例如,你可以用TPL来验证数据的合法性。

using namespace tpl;
 
std::string str;
std::cin >> str;
if (str == real())
   std::cout << str << " is a real value.\n";
else
   std::cout << str << " isn't a valid real value. Please input again.";

这个例子是用TPL验证一个输入的字符串是不是合法浮点数。但是这对TPL来说,是牛刀小试(注意我不是说用TPL做这样的事情性能不好,事实上它有很好的性能)。

如果没有本文要介绍的标记(Mark)和动作(Action)(这样我没有提约束(Restriction),是因为它和前两者的目的不同),不足以释放TPL的能量。下面我们一一说明。

为什么这三者会一起说明,原因其实在于它们都用TPL的同一个算符:operator/。operator/具有多种含义,包括:

  • 标记(Mark)
  • 动作(Action):包括赋值(Assignment)和其他类型的动作
  • 约束(Restriction)

本文的主旨就在于给大家展示operator/的多种用途。

标记(Mark)

如果你了解过正则表达式(regex,我希望你了解过,因为这是理解TPL库的基础),应该听说过捕获(Capture)一词。捕获(Capture)其实就是这里的标记(Mark)。它本身不属于正则匹配的语法之一。但是如果一个语法只能匹配,没有办法做标记(Mark)── 捕获有意义的数据,那么显然其能力就有限(可能真的就象前面一样,只能做输入合法性的验证了)。

我们来看下标记(Mark)的具体实例。本样例的代码参见:tpl/examples/json-print/Simplest.cpp

typedef DOM<> dom;

const char source[] = "\
    class Foo // Foo comment\n\
      : public Base1, Base2\n\
    {};\
";

dom::Mark tagName("name");
dom::NodeMark tagBase("base", true);
    dom::Mark tagAccess("access");
    //dom::Mark tagName("name");

dom::Allocator alloc;
dom::Document doc(alloc);

source >> cpp_skip_
    [
        gr(c_symbol_("class")) + c_symbol()/tagName +
        !(':' +
            (
                !gr(c_symbol_("public")/tagAccess) +
                c_symbol()/tagName
            )/tagBase % ','
        ) +
        '{' + '}' + ';'
    ]/doc;

std::OutputLog log;
json_print(alloc, log, doc);

这是一个蛮复杂的例子。其中包含了我还没有展开讲的Grammar(语法)的成分。输出结果:

{
  "name": "Foo",
  "base": 
  [
    {
      "access": "public",
      "name": "Base1"
    },
    {
      "name": "Base2"
    }
  ]
}

动作(Action)

标记和动作(Mark and Action)是达到同一个目的的两种手段。

引入动作(Action)从哲学上来说是一种无奈之举(虽然有了动作之后,确实很强大)。TPL我多次称之为Text Processing Language,而不是Text Process Library,因为我认为它是一种新的语言。虽然它用C++实现,但是它的理念和C++不同。这是一种描述性的语言,你只需要描述事实,而不是执行命令。但是动作(Action)一定程度上打破了这一哲学。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License