Clojure中的递归下降解析器
我正在用Clojure创建一些专家系统,我需要开发递归下降解析器,用于从文本文件读取规则并从中创建Clojure函数。我编写了一个函数,它检查文本文件是否符合我的语法,它给我一个字符串列表和元素,如函数名、数字、系统事实名称、算术和逻辑运算符。我的语法就是这样的:Clojure中的递归下降解析器,clojure,expert-system,recursive-descent,Clojure,Expert System,Recursive Descent,我正在用Clojure创建一些专家系统,我需要开发递归下降解析器,用于从文本文件读取规则并从中创建Clojure函数。我编写了一个函数,它检查文本文件是否符合我的语法,它给我一个字符串列表和元素,如函数名、数字、系统事实名称、算术和逻辑运算符。我的语法就是这样的: RULE := EXPR >> FACT EXPR := ( WSK OpA NUM ) || ( FACT ) || ( EXPR OpL EXPR ) || (WSK OpA WSK) OpL := AND
RULE := EXPR >> FACT
EXPR := ( WSK OpA NUM ) || ( FACT ) || ( EXPR OpL EXPR ) || (WSK OpA WSK)
OpL := AND || OR
OpA := > || < || ==
WSK := [A-Z]+
FACT := [a-z]+
NUM := [0-9]+\.?[0-9]*
现在我想从上面函数提供给我的字符串列表中创建一个clojure函数。你知道怎么做吗
更新
以下是规则和硬编码版本的示例:
(ROC>100)>>购买
你试过了吗
它从上下文无关的语法生成解析器
(ns example.core
(:require [instaparse.core :as insta])
(def as-and-bs
(insta/parser
"S = AB*
AB = A B
A = 'a'+
B = 'b'+"))
首先,我同意@Arthur关于生成语法的使用 下一步是编写一个函数,将语法转换为表示代码的Clojure数据结构 例如,如果语法解析为
[:S [:EXPR [:WSK "ROC"] [:OpA ">"] [:NUM "100"]] :>> [:FCT "BUY"]] ; "ROC > 100 << BUY"
试着跑步
(parse-expr [:EXPR [:WSK "B"] [:OpA "<"] [:NUM "1"]])
(parse expr[:expr[:WSK“B”][:OpA“您是否可以再包含一点上下文(双关语);)在哪里定义了acceptFACT acceptLP等。在您的示例中,ROC来自哪里(现有函数、参数等)?如果您调用它,它看起来像一个函数。另外,外部函数是否接受任何参数?我现在假设为函数,没有参数。语法正确吗?它不支持WSK和FACT有多个字符,FACT中只有小写,而您给出的示例使用大写。同样的问题我不知道它是从哪里来的。既然你没有调用它,我就假设变量,虽然它看起来也像一个字符串。好的,我更新了我的更新。deterb,ROC是一个没有参数的函数,我想返回字符串“BUY”"如果名为ROC的函数返回的值大于100。我还更新了语法,所以现在WSK和FACT可以有多个字符。感谢您的回答。我将研究它的文档并尝试在我的项目中使用。您能看一下吗?好的,但我是否可以创建一个字符串表达式,其中str函数使用适当的元素我还想在一些列表中列出我的规则,这样我就可以检查该列表,看我是否可以运行一些规则并生成新的事实。你不需要生成字符串,然后使用str
对其求值。我希望代码生成类似(列表(符号)的内容“deterb但(变量部分1 val)是什么意思例如?因为在此上下文中无法解析symbol:variable时出错。应该是var
,而不是variable
,很抱歉。运行时,您需要确保有一个具有该名称且可访问的变量。您可能希望改为将其解析为符号;我对您的运行代码是为了告诉您哪个更合适。感谢您的解释。我改用了symbol,但宏的扩展有一些问题。我想作为generate funcs的参数传递,比如(语法行),其中行是字符串,语法是我声明的语法分析器。这是一个问题,因为generate funcs宏上有引号。
[:S [:EXPR [:WSK "ROC"] [:OpA ">"] [:NUM "100"]] :>> [:FCT "BUY"]] ; "ROC > 100 << BUY"
(defn parse-expr [expr]
(let [[_ [part1-type part1-val] [part2-type part2-val] [part3-type part3-val]] expr]
(if (and (= :WSK part1-type) (= :OpA part2-type) (= :NUM part3-type))
(let [wsk (variable part1-val)
opa (variable part2-val)
num (Integer/valueOf part3-val)]
(list opa (list wsk) num)))))
(defmacro generate-funcs [parse-tree]
(let [[_ expr _ [_ fact]] parse-tree
expr (parse-expr expr)
fact (symbol fact)]
`(fn [] (if ~expr (str ~fact) ()))))
(parse-expr [:EXPR [:WSK "B"] [:OpA "<"] [:NUM "1"]])
(macroexpand-1 '(generate-funcs [:S [:EXPR [:WSK "B"] [:OpA "<"] [:NUM "1"]] :>> [:FCT "b"]]))