2

我一直在尝试让一个简单的 reg-ex 在 Clojure 中工作,以测试一些 SQL 保留字(select、from、where 等)的字符串,但无法让它工作:

(defn areserved? [c]
  (re-find #"select|from|where|order by|group by" c))

(我用空格分割一个字符串,然后遍历所有单词)

帮助将不胜感激,

谢谢!


编辑:我的第一个目标(在只阅读了一些示例和基本 Clojure 材料之后)是解析一个字符串并为它的每个部分(即单词)返回它们在语句中的“工作”(保留字、字符串等)。 )。

到目前为止我所拥有的:

(use '[clojure.string :only (join split)])

(defn isdigit? [c]
  (re-find #"[0-9]" c))

(defn isletter? [c]
  (re-find #"[a-zA-Z]" c))

(defn issymbol? [c]
  (re-find #"[\(\)\[\]!\.+-><=\?*]" c))

(defn isstring? [c]
  (re-find #"[\"']" c))

(defn areserved? [c]
  (if (re-find #"select|from|where|order by|group by" c)
      true
      false))

(defn what-is [token]
  (let [c (subs token 0 1)]
    (cond
      (isletter? c)  :word
      (areserved? c) :reserved
      (isdigit? c)   :number
      (issymbol? c) :symbol
      (isstring? c) :string)))

(defn checkr [token]
  {:token token
   :type (what-is token)})

(defn goparse [sql-str]
  (map checkr (.split sql-str " ")))

感谢所有的帮助家伙!很高兴看到对这种相对较新的语言有如此多的支持(至少对我来说:))

4

1 回答 1

4

我不完全确定您到底想要什么,但这里有一些变体可以将您的第一个正则表达式匹配强制为布尔值:

(defn areserved? [c]
  (string?
    (re-find #"select|from|where|order by|group by"c)))

(defn areserved? [c]
  (if (re-find #"select|from|where|order by|group by"c)
      true
      false))

更新以回应问题编辑:

感谢您发布更多代码。不幸的是,这里有许多问题,我们可以尝试通过以简单和幼稚的方式修补现有代码来解决,但它只会让您到目前为止,在您使用这种单次迭代方法遇到下一个问题之前。

@alex 是正确的,如果您已经用空格分割字符串,您的areserved?方法将无法匹配。order by也就是说,一个简单的解决方法是将orderby视为单独的关键字(它们是,即使它们总是一起出现)。

下一个问题是该areserved?函数将匹配字符串中的关键字,但您将它调度到what-is函数中的一个字符。您几乎总是在condfor中找到匹配项isletter?,因此您会将所有内容标记为“单词”。

总而言之,您似乎试图在map.

我不确定你这样做是否只是为了玩 Clojure 的乐趣(这令人钦佩 - 继续前进!),在这种情况下,如果你继续使用这种简单的解析方法可能并不重要......你一定会学到一些东西;但是,如果您想更进一步并更成功地解析 SQL,那么我建议您阅读一些关于Lexing解析和构建抽象语法树(AST) 的内容可能会有所帮助。

Brian Carper 写过关于使用Clojure 的 Java 解析器生成器“ANTLR”的文章——它已经有几年历史了,但可能值得一看。

您还可以从关于 lexing and parsing SQL 的 F# 编程书籍的本章中获得一些可转移的想法。

于 2013-01-15T18:32:16.657 回答