我正在考虑如何为我为 CSS 和 JS 找到的几个库创建一个 PHP 等价物。
一个是Less CSS
这是 dynamic stylesheet language
. Less CSS
背后的基本思想是它允许您创建更多动态 CSS 规则,其中包含“常规”CSS 不支持的实体,例如 mixins
, functions
等等,然后是最后的 Less CSS
将这些语法编译到常规 CSS 中。
另一个有趣的 JS 库以(某种)类似的模式运行是 CoffeeScript
您可以在其中编写“更整洁、更简单”的代码,然后将其编译为常规 Javascript。
如何为 PHP 创建一个简单的类似界面?就像概念证明一样;我只是想学习东西。让我们以扩展类的简单用例为例。
class a
{
function a_test()
{
echo "This is test in a ";
}
}
class b extends a
{
function b_test()
{
parent::a_test();
echo "This is test in b";
}
}
$b = new b();
$b->b_test();
假设我想让用户写类 b
如(仅举个例子):
class b[a] //would mean b extends a
{
function b_test()
{
[a_test] //would mean parent::a_test()
echo "This is test in b";
}
}
然后让他们稍后将该代码“解析”为常规 PHP(我相信通常通过运行单独的命令/进程)。我的问题是我将如何着手创建这样的东西。可以用 PHP 完成吗,我需要使用 C/C++ 之类的东西吗?如果我要解决这个问题,我应该如何解决?网上有资源吗?非常感谢任何指点!
最佳答案
语言转码器并不像人们想象的那么容易。
您提供的示例可以很容易地通过 preg_replace
实现,它查找类定义并将 [a]
替换为 extends a
。
但更复杂的功能需要一个转码器,它是一组较小的逻辑代码片段。
在大多数程序员术语中,人们错误地将转码器称为编译器,但编译器和转码器之间的区别在于编译器读取源代码并输出原始二进制机器代码,而转码器读取源代码并输出(不同的)源代码。
例如,PHP(或 JavaScript)运行时既不是编译器也不是转码器,而是解释器。
行话说完了,让我们来谈谈转码器:
要构建转码器,您必须首先构建分词器,它将源代码分解为分词,这意味着如果它看到一个完整的单词,例如“类”或类名或“函数”或名称一个函数,它捕获那个词并将其视为一个标记。当它遇到另一个标记,例如左圆括号或左大括号或方括号等时,它会认为是另一个标记。
幸运的是,token_get_all 已经轻松扫描了 PHP 中可用的所有可识别标记。这是 PHP 捆绑的一个函数。您可能会遇到一些麻烦,因为 PHP 假设了一些关于您如何使用符号的事情,但总而言之,您可以使用此函数。
分词器创建它找到的所有分词的平面列表,并将其提供给解析器。
解析器是代码转换器的第二阶段,它读取 token 列表并决定诸如“如果 token [0] 是一个类并且 token [1] 是一个名称_值那么我们有一个类”等。之后遍历整个标记列表,我们应该有一个抽象语法树。
抽象语法树是一种仅象征性地保留有关源代码的相关信息的结构。
$ast = array(
'my_derived_class' => array(
'implements' => array(
'my_interface_1',
'my_interface_2',
'my_interface_3'),
'extends' => 'my_base_class',
'members' => array(
'my_property_name' => 'my_default_value',
'my_method_name' => array( /* ... */ )
)
)
);
获得抽象语法树后,您需要遍历它并输出目标源代码。
真正棘手的部分是解析器(取决于您正在解析的语言的复杂性)可能需要回溯算法或某种其他形式的模式匹配来区分相似情况。
我建议阅读 Terence Parr 的书 http://pragprog.com/book/tpdsl/language-implementation-patterns其中详细描述了编写转码器所需的设计模式。
在 Terrence 的书中,您会发现为什么某些语言(如 HTML 或 CSS)比 PHP 或 JavaScript 更简单(在结构上),以及这与语言解析器的复杂性有何关系。
关于php - 创建自定义 PHP 语法分析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12717084/