1

我写了一个词法分析器和解析器来分析线性代数语句。每个语句由一个或多个表达式和一个或多个声明组成。我正在使用 menhir 和 OCaml 编写词法分析器和解析器。

例如:Ax = b,其中 A 是可逆的。

这应该读作 A * x = b, (A, invertible)

在表达式中,所有 id 必须是大写或小写符号。我想重载乘法运算符,以便用户不必输入“*”符号。

但是,由于词法分析器还需要能够读取字符串(例如本例中的“可逆”),因此表达式的“Ax”部分作为字符串发送到解析器。这会导致解析器错误,因为在语句的表达式部分不应遇到任何字符串。

这是语法的基本思想

stmt :=
  | expr "."
  | decl "."
  | expr "," decl "."

expr :=
  | term
  | unop expr
  | expr binop expr

term :=
  | <int> num
  | <char> id
  | "(" expr ")"

decl :=
  | id "is" kinds

kinds :=
  | <string> kind
  | kind "and" kinds

有什么方法可以分隔各个字符并告诉解析器它们应该被视为乘法吗?有没有办法改变词法分析器,让它足够聪明地知道逗号之前的所有字符簇都是 ids 并且之后的所有簇都应该被视为字符串?

4

1 回答 1

3

在我看来你有两个问题:

  1. 您希望您的词法分析器在不同的地方以不同的方式处理字符序列。

  2. 您希望通过相邻的表达式来指示乘法(中间没有运算符)。

我将在词法分析器中解决的第一个问题。

一个问题是为什么你说你需要使用字符串。这意味着您可以说一系列完全开放的事情。这可能是真的,但如果您可以将自己限制在一个较小的数字,您可以使用关键字而不是字符串。例如,invertible将是一个关键字。

如果你真的想在这些地方允许任何字符串,那么绝对仍然可以破解一个词法分析器,以便它保持一个描述它所看到的状态,并展望未来会发生什么。如果您不需要遵守预定义的语法,您可以调整语法以使其更容易。(例如,您只能将逗号用于一个目的。)

对于第二个问题,我会说您需要在语法中添加邻接。即,您的语法需要一条类似term := term term. 我怀疑让它正常工作很棘手,但它在 OCaml(其中相邻的表达式表示函数应用程序)和 awk(其中相邻的表达式表示字符串连接)中确实有效。

于 2014-04-20T16:29:00.377 回答