目前我的前端可以解析像 123
这样的正则表达式, "abcd"
, "=123"
, "=TRUE+123"
...以下是相关代码:
(* in `syntax.ml`: *)
and expression =
| E_integer of int
| E_string of string
(* in `parser.mly`: *)
expression:
| INTEGER { E_integer $1 }
| STRING { E_string $1 }
现在我想改进解析器,这样,当我们遇到以 =
开头的字符串时,我们尝试将其计算为公式,而不是文字字符串。所以syntax.ml
变成:
(* in `syntax.ml`: *)
and expression =
| E_integer of int
| E_string of string
| E_formula of formula
and formula =
| F_integer of int
| F_boolean of bool
| F_Add of formula * formula
问题是我不知道如何更改parser.mly
,我尝试了这个,但没有成功( This expression has type string but an expression was expected of type Syntax.formula
):
(* in `parser.mly`: *)
expression:
| INTEGER { E_integer $1 }
| STRING {
if String.sub $1 1 1 <> "="
then E_string $1
else E_formula (String.sub $1 2 ((String.length $1) - 1)) }
我不知道如何让解析器知道以 =
开头的字符串,我需要根据 formula
的规则进一步解析它...有人可以帮忙吗?
根据 gasche
的评论:
我同意我需要一个公式解析器。现在的问题是我是否需要单独的 lexer.mll
对于公式。我希望不会,因为逻辑上只对整个程序进行一次 lex 处理,不是吗?另外,我可以直接将公式语法添加到现有的 parser.mly
中吗? ?
当前lexer.mll
,我有:
let STRING = double_quote ([^ '\x0D' '\x0A' '\x22'])* double_quote
rule token = parse
| STRING as s { STRING s }
我想我可以直接在这里做一些事情:
let STRING = double_quote ([^ '\x0D' '\x0A' '\x22'])* double_quote
let FORMULA_STRING = double_quote = ([^ '\x0D' '\x0A' '\x22'])* double_quote
rule token = parse
| FORMULA_STRING as fs { XXXXX }
| STRING as s { STRING s }
我不知道应该在 XXXXX
的地方写什么,应该是 Parser_formula.formula token fs
,在我单独有 parser_formula.mly
的情况下?如果我只有parser.mly
怎么办?其中包含所有语法,包括公式语法?
最佳答案
问题出在你的线路上
else E_formula (String.sub $1 2 ((String.length $1) - 1))
而不是 (String.sub ...)
,其类型为 string
,您应该返回 Syntax.formula
类型的值。如果您有 parse_formula : string -> Syntax.formula
您可以在这里编写函数
else E_formula (parse_formula (String.sub $1 2 ((String.length $1) - 1)))
我认为您可以通过首先将公式语法定义为单独的解析器来定义这样的函数。
编辑:按照您自己的编辑:
如果您选择为公式调用不同的解析器,则无需定义不同的词法分析器
如果您选择在词法分析器级别处理字符串和公式之间的区别(您确定这是正确的吗?以“=”开头的真实字符串怎么样?),那么您不需要一个单独的公式解析器,您可以将它们作为当前语法中的规则。但要做到这一点,您需要词法分析器以更细粒度的方式处理公式:而不是仅仅识别
"=.*"
作为单个 token ,您应该认识"=
作为公式的开头,lex 为公式的其余部分,直到遇到结束"
。为了避免冲突,您可能希望使用词法规则而不是简单的正则表达式来处理简单的字符串。
如果你能让第二种方法发挥作用,我认为这确实是一个更简单的想法。
PS:请使用menhir变量命名工具而不是$1
一旦变量不连续(由于中间终端)或者您需要重复多次。
关于parsing - 进一步解析特殊情况下的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13958557/