2

好吧,这是我的问题:我有一个使用自定义 Javascript 实现的应用程序,但不支持正则表达式。

但是,我仍然希望能够解析模板;最好使用 C++。

模板可能如下所示(ASP 样式模板):

<% var foo = someFunction("with a string");
   var bar =  anotherFunction(["with", "an", "array"]); %>

<b>This is html, and this is a variable: <%= bar %></b>

<% if(foo) { %>
    <b> foo is 'true'</b>
<% } else { %>
    <b> foo is 'false'. terrible. </b>
<% } %>

所以一般结构非常简单(我假设,相对可解析)。

我的问题是,是否可以使用while()循环解析这样的模板,遍历每个字符,而不是使用正则表达式?

既然我这样做的尝试失败了,那怎么能做到呢?

谢谢!

4

4 回答 4

3

这样的模板很容易解析。

关键是要认识到此类模板基本上只包含两种字符串的序列:样板 (HTML) 文本和脚本文本。

样板文本基本上以“%>”开头,以“<%”结尾(特殊情况在 begin-template 和 end-template 处)。脚本文本就是其他一切。是的,你可以只用一个 while 循环来为每个监视“<%”、“%>”或“模板结束”的循环选择两者。该序列隐含在来回交替中。这使得解析器非常简单:

  while not eof
       boilerplate="";
       while next_characters~="<%" or eof
          boilerplate concat next_characters
       end
       scripttext="";
       while next_characters~="%>" or eof
          scripttext concat next_characters
       end
  end

(我将单个字符管理的细节留给编码器)。

你没有说的是你想对解析结果做什么。如果目标是从解析结果中“生成输出”,则必须将其转换为程序。这实际上很容易。

基本上,您将结果写入文件并编译它。对于每条收集的样板文本,发出一个打印样板文本的打印语句;您可能必须转义字符以使它们在您选择的目标语言的字符串文字中合法,或者将样板文件分成多个块以打印它。对于每个脚本文本块,只需发出不变的内容。您可能必须发出一个 prolog 文本块来制作函数标题,并作为 postlog 文本块来制作函数结束。

而已。

[因为这样的“模板”和带有打印语句的简单程序之间的简单转换,我觉得这样的模板编程不是很诱人。它为我节省了一些打印关键字,仅此而已。]

于 2012-07-08T04:39:06.063 回答
1

您是否考虑过使用有限状态机?这里有一些链接供您查看。

简而言之:FSM 由有限数量的状态和这些状态之间的转换组成。因此,您的解析过程可能表示如下(伪代码):

myFSM = new FSM( /* states, transitions */ );
// now your FSM is at initial state.

while not end of file {       
  switch (myFSM->currentState) {   
    case 'IF':
      // Does current line contain closing if? or else? If so, do a transition
      // to state that grabs everything in if construct 
      ...
    case 'TEXT': 
      // Lines do not have any lexical constructs, and we are outside any blocks
      ...
    ...

  }
}

当然,这大大简化了。真正的解析器看起来会有所不同。但我希望你有一个想法。

于 2012-07-02T18:41:11.773 回答
1

这就是我在你的情况下会尝试的:

  1. 编写一个标记器,它返回一组已知标记(附有它们所代表的确切字符串,例如ID("someFunction"):)

  2. 使用上述描述可接受的模板格式的标记编写正式语法

  3. 编写识别语法的解析器(例如下推自动机LR 解析器LALR 解析器))

注意:确保语法符合您正在实现的解析器的限制;如果没有,请重新编写语法或更改解析器

注意:确保您彻底测试您的解析器,因为实现中的错误可能难以调试

注意:在解析步骤中,如果您想获取已解析模板的语义(含义),而不仅仅是它是否是有效模板,您还需要执行一些附加操作。这些额外的步骤包括存储变量/函数的 ID(还记得附加到标记的字符串吗?),在引用时查找它们,检查函数参数编号等。

于 2012-07-02T17:04:11.740 回答
0

可能已经有适合您的现有解决方案。

无逻辑模板库:

https://github.com/leonidas/transparency/wiki/Frequently-Asked-Questions

(见最后一个问题)。

于 2012-07-08T09:35:43.057 回答