8

作为一个宠物项目,我想尝试实现一种我自己设计的基本语言,可以用作网络脚本语言。将 C++ 程序作为 Apache CGI 运行是微不足道的,因此真正的工作在于如何解析包含非代码(HTML/CSS 标记)和服务器端代码的输入文件。

在我本科的编译器课程中,我们使用FlexBison为一种简单的语言生成扫描器和解析器。我们得到了一份语法副本,并编写了一个解析器,将简单的语言翻译成虚拟机的简单程序集。flex 扫描器对输入进行标记,并将标记传递给 Bison 解析器。

这与我想做的不同之处在于,就像 PHP 一样,这种语言可以有纯 HTML 标记,而脚本语言可以像下面这样穿插:

<p>Hello,
<? echo "World ?>
</p>

我假设按如下方式解析输入文件会很有效,我是否不正确:

  1. 扫描输入,直到找到脚本开始标记('
  2. 第二个扫描器标记输入文件的服务器端脚本部分(来自打开标记:'')并将标记传递给解析器,它不需要知道文件中的标记。
  3. 控制权返回到继续这种一般模式的第一个扫描仪。

基本上,第一个扫描器只区分标记(直接返回到浏览器未修改)和代码,它被传递给第二个扫描器,第二个扫描器反过来标记代码并将标记传递给解析器。

如果这不是一个可靠的设计模式,PHP 等语言如何有效地处理扫描输入和解析代码?

4

2 回答 2

7

您想查看开始条件。例如:

"<?"            { BEGIN (PHP); }
<PHP>[a-zA-Z]*  { return PHP_TOKEN; }
<PHP>">?"       { BEGIN (0); }
[a-zA-Z]*       { return HTML_TOKEN; }

您从状态 0 开始,使用 BEGIN 宏来更改状态。要仅在特定状态下匹配 RE,请在 RE 前面加上用尖括号括起来的状态名称。

In the example above, "PHP" is state. "PHP_TOKEN" and "HTML_TOKEN" are _%token_s defined by your yacc file.

于 2008-09-21T15:23:08.113 回答
2

PHP 不区分扫描和标记。它只是在标记模式下输出到缓冲区,然后在代码模式下切换到解析。您不需要两遍扫描仪,只需一个弹性词法分析器即可完成此操作。

如果您对 PHP 本身的工作原理感兴趣,请下载源代码(试试 PHP4 源代码,它更容易理解)。您要查看的是 Zend 目录中的zend_language_scanner.l.

我自己写过类似的东西,我真的建议重新考虑走 Flex 和 Bison 路线,并使用像Antlr这样的现代东西。它更容易、更容易理解(lex 语法中使用的宏变得非常混乱且难以阅读)并且它具有内置调试器(AntlrWorks),因此您不必花费数小时查看 3 Meg 调试文件. 它还支持多种语言(Java、c#、C、Python、Actionscript),并拥有一本优秀的书籍和一个非常好的网站,应该能够让您立即启动并运行。

于 2008-09-19T20:06:15.517 回答