- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试培养一些词法分析/解析语法的技能。我回顾了我为 SQL 编写的一个简单解析器,我对它并不完全满意——似乎应该有一种更简单的方法来编写解析器。
SQL 让我很困惑,因为它有很多可选标记和重复。例如:
SELECT *
FROM t1
INNER JOIN t2
INNER JOIN t3
WHERE t1.ID = t2.ID and t1.ID = t3.ID
相当于:
SELECT *
FROM t1
INNER JOIN t2 ON t1.ID = t2.ID
INNER JOIN t3 on t1.ID = t3.ID
ON
和 WHERE
子句是可选的,并且可以出现多次。我在解析器中处理这些内容如下:
%{
open AST
%}
// ...
%token <string> ID
%token AND OR COMMA
%token EQ LT LE GT GE
%token JOIN INNER LEFT RIGHT ON
// ...
%%
op: EQ { Eq } | LT { Lt } | LE { Le } | GT { Gt } | GE { Ge }
// WHERE clause is optional
whereClause:
| { None }
| WHERE whereList { Some($2) }
whereList:
| ID op ID { Cond($1, $2, $3) }
| ID op ID AND whereList { And(Cond($1, $2, $3), $5) }
| ID op ID OR whereList { Or(Cond($1, $2, $3), $5) }
// Join clause is optional
joinList:
| { [] }
| joinClause { [$1] }
| joinClause joinList { $1 :: $2 }
joinClause:
| INNER JOIN ID joinOnClause { $3, Inner, $4 }
| LEFT JOIN ID joinOnClause { $3, Left, $4 }
| RIGHT JOIN ID joinOnClause { $3, Right, $4 }
// "On" clause is optional
joinOnClause:
| { None }
| ON whereList { Some($2) }
// ...
%%
换句话说,我通过将可选语法分解为单独的规则来处理可选语法,并使用递归处理重复。这可行,但它将解析分解为一堆小子例程,并且很难看出语法实际代表什么。
我认为如果我可以在括号内指定可选语法并用 * 或 + 重复,那么编写起来会容易得多。这会将我的 whereClause 和 joinList 规则减少为以下内容:
whereClause:
| { None }
// $1 $2, I envision $2 being return as an (ID * op * ID * cond) list
| WHERE [ ID op ID { (AND | OR) }]+
{ Some([for name1, op, name2, _ in $1 -> name1, op, name2]) }
joinClause:
| { None }
// $1, returned as (joinType
// * JOIN
// * ID
// * ((ID * op * ID) list) option) list
| [ (INNER | LEFT | RIGHT) JOIN ID [ON whereClause] ]*
{ let joinType, _, table, onClause = $1;
Some(table, joinType, onClause) }
我认为这种形式更更容易阅读,并且更直观地表达了它试图捕获的语法。不幸的是,我在 Ocaml 或 F# 文档中找不到任何支持此表示法或类似内容的内容。
是否有一种简单的方法可以在 OcamlYacc 或 FsYacc 中表示具有可选或重复标记的语法?
最佳答案
当你组合所有的小片段时,你应该会得到你想要的东西。而不是:
(INNER | RIGHT | LEFT )
你刚刚
inner_right_left
并将其定义为这三个关键字的并集。
您还可以在词法分析器中定义并集。在您定义 token 的方式中,或者使用 camlp4 中,我在该领域没有做太多事情,所以我不能建议您采取这些路线。而且我认为它们不会像到处都有小部件那样适合您。
编辑:
因此,对于 camlp4,您可以查看 Camlp4 Grammar module和一个tutorial和一个better tutorial 。请注意,这并不完全是您想要的,但已经非常接近了。该文档非常糟糕,如 recent discussion on the ocaml groups 中所示。 ,但对于这个特定领域,我认为你不会有太多问题。我用它做了一些工作,可以回答更多问题。
关于f# - 使用 OcamlYacc/FsYacc 表示可选语法和重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/533808/
如果我使用 FSYacc 生成解析器,它会是线程安全的吗? 我问的唯一原因是因为功能 Parsing.rhs_start_pos 和 Parsing.symbol_end_pos 似乎没有向它们传递任
我开始玩 Fslex/Fsyacc。尝试使用此输入生成解析器时 解析器.fsy: %{ open Ast %} // The start token becomes a parser function
我正在使用 F# Power Pack 中的 fsyacc/fslex 来解析一些源代码。 为了检测错误,我使用以下代码: use inputChannel = new StreamReader(Fi
我知道可以将参数传递给词法分析器: rule tokenize scope = parse | whitespace { tokenize scope lexbuf
在阅读了一个 2 年历史的网页后,与他们的 OCamel 同行相比,它确实撕裂了 fslex/fsyacc、错误、缓慢、愚蠢等,我想知道什么是词法解析需求的最佳选择? 我以前用 C# 绑定(bind)
fslex 和 fsyacc 工具目前需要 2 阶段编译,生成文件,然后由 fsc 编译。在我看来,如果源文件是嵌入式资源,以编程方式提供给 fslex 和 fsyacc,并且生成的代码使用 Code
我正在尝试培养一些词法分析/解析语法的技能。我回顾了我为 SQL 编写的一个简单解析器,我对它并不完全满意——似乎应该有一种更简单的方法来编写解析器。 SQL 让我很困惑,因为它有很多可选标记和重复。
这个问题不太可能帮助任何 future 的访客;它仅与一个小地理区域、一个特定时刻或一个非常狭窄的情况相关,而这些情况通常不适用于互联网的全局受众。如需帮助使这个问题更广泛地适用,visit the
我正在使用 FsLex 和 FsYacc 在 F# 应用程序中进行字符串解析。在抽象语法树 (AST) 创建期间,解析器必须决定如何创建 AST(创建不同的树、抛出异常等)。解析器行为必须取决于几个参
我需要解析如下简单的 DSL 语言: import "library.txt" def main(int param1, bool param2) { var a = f4(param1);
我正在使用 F# 开发玩具编译器,即 FsLex 和 FsYacc 的组合。为了熟悉它们,我阅读了 Expert F# (v2) 一书(一本好书)的 Lexer/Parser 章节。现在,我已经完成了
我正在学习 F#,因为我想编写一个词法分析器和解析器。我对这种处理有一点经验,但确实需要像 F# 一样正确地学习它。 在学习 F# 的词法/解析功能时,学习 lex 和 yacc 就足够了吗? 或者是
我遇到了 FSlex/FSyacc 在我的机器上崩溃的问题。 在上下文中,这是在 Parallels 虚拟机内运行的 Windows 8 Consumer Preview(32 位)上运行的 Visu
我在 Visual Studio 中使用 fsyacc(使用 Parsed Language Starter 模板),但构建输出没有显示发生错误的行/列(仅:fsyacc 退出,代码为 1)。我必须从
我是一名优秀的程序员,十分优秀!