Permalink
Browse files

Removed regular-expressions from gluer.clauses.

The gluer.parser now includes the matched groups for regular
expression terminals. This means there is only one place where
the regular expressions are managed (in gluer.resources). It can
be improved further, by having named capture groups, but this
requires a lot more refactoring.
  • Loading branch information...
aroemers committed Oct 30, 2012
1 parent dc9ab86 commit 3e377cb0feae2453a856b0cf40dc6ded436001a2
Showing with 46 additions and 27 deletions.
  1. +26 −22 src/gluer/clauses.clj
  2. +10 −1 src/gluer/parser.clj
  3. +10 −4 src/gluer/resources.clj
View
@@ -57,6 +57,15 @@
(ffirst where-clause)))
+;;; Helper functions.
+
+(defn- full-class-name
+ "Returns the fully qualified class name, based on a package name and class
+ name. The package may be nil."
+ [package class-name]
+ (str package (when package ".") class-name))
+
+
;;; The 'new' what clause.
(defmethod check-what :what-clause-new
@@ -98,20 +107,18 @@
(defmethod check-what :what-clause-call
[association]
- (let [what (get-in association [:what :what-clause-call :method :word])
- matched (re-matches #"((\w+\.)+)(\w+)\(.*\)" what)
- class-name (apply str (butlast (second matched)))]
+ (let [{:keys [word match]} (get-in association [:what :what-clause-call :method])
+ class-name (full-class-name (nth match 1) (nth match 2))]
(if-let [ctclass (r/class-by-name class-name)]
- (check-expression what)
+ (check-expression word)
(format "Class %s in the `new' clause not found. Please check the name or classpath."
class-name))))
(defmethod type-of-what :what-clause-call
[what-clause]
- (let [what (get-in what-clause [:what-clause-call :method :word])
- matched (re-matches #"((\w+\.)+)(\w+)\(.*\)" what)
- class-name (apply str (butlast (second matched)))
- method-name (nth matched 3)
+ (let [match (get-in what-clause [:what-clause-call :method :match])
+ class-name (full-class-name (nth match 1) (nth match 2))
+ method-name (nth match 3)
ctclass (r/class-by-name class-name)
method (first (filter #(= (.getName %) method-name) (.getMethods ctclass)))]
(.getName (.getReturnType method))))
@@ -146,40 +153,37 @@
(defmethod check-where :where-clause-field
[association]
- (let [where (get-in association [:where :where-clause-field :field :word])
- matched (re-matches #"((?:\w+\.)+)(\w+)" where)
- class-name (apply str (butlast (second matched)))
- field-name (nth matched 2)]
+ (let [match (get-in association [:where :where-clause-field :field :match])
+ class-name (full-class-name (nth match 1) (nth match 2))
+ field-name (nth match 3)]
(if-let [ctclass (r/class-by-name class-name)]
(try
(let [field (.getDeclaredField ctclass field-name)]
- nil) ;--- TODO: Check if field has init code or injection is overwritten in a constructor.
+ nil) ;--- Check if field has init code or injection is overwritten in a constructor?
(catch javassist.NotFoundException nfe
(format "Class %s does not have a field named %s." class-name field-name)))
(format "Class %s cannot be found. Please check the name or classpath."))))
(defmethod type-of-where :where-clause-field
[where-clause]
- (let [where (get-in where-clause [:where-clause-field :field :word])
- matched (re-matches #"((?:\w+\.)+)(\w+)" where)
- class-name (apply str (butlast (second matched)))
- field-name (nth matched 2)
+ (let [match (get-in where-clause [:where-clause-field :field :match])
+ class-name (full-class-name (nth match 1) (nth match 2))
+ field-name (nth match 3)
ctclass (r/class-by-name class-name)
field (.getDeclaredField ctclass field-name)]
(.getName (.getType field))))
(defmethod transforms-classes :where-clause-field
[association]
- (let [where (get-in association [:where :where-clause-field :field :word])
- matched (re-matches #"((?:\w+\.)+)(\w+)" where)]
- #{(apply str (butlast (second matched)))}))
+ (let [match (get-in association [:where :where-clause-field :field :match])]
+ #{(full-class-name (nth match 1) (nth match 2))}))
(defmethod inject-where :where-clause-field
[where-clause ctclass retrieval-code]
(let [constructors (.getDeclaredConstructors ctclass)
- where (get-in where-clause [:where-clause-field :field :word])
- field-name (nth (re-matches #"((?:\w+\.)+)(\w+)" where) 2)
+ match (get-in where-clause [:where-clause-field :field :match])
+ field-name (nth match 3)
constructor-code (format "_inject_%1$s();" field-name)
field-code (format "private boolean _%1$s_injected;" field-name)
method-code (format
View
@@ -1,4 +1,13 @@
;;;--- TODO: Make parser a stand-alone library.
+;;;
+;;;--- TODO: Add parse functions for regular expression terminals,
+;;; so one could have for instance {:call {:word "alice.bob.Foo$Bar.get(true)"
+;;; :line-nr 1
+;;; :data {:class-name "Foo$Bar"
+;;; :package "alice.bob"
+;;; :method-name "get"}}}
+;;;
+;;;--- TODO: How to deal with [:foo*] rules, where errors in parsing :foo are lost?
(ns gluer.parser
(:use [clojure.string :only (split split-lines join)]))
@@ -21,7 +30,7 @@
word (:word token)]
(if token
(if-let [match (re-matches re word)]
- {:succes token;(if (vector? match) (first match) match)
+ {:succes (assoc token :match match)
:remainder (rest remainder)}
{:error (str "Unexpected token '" word "' on line " (:line-nr token)
", expected a word matching the regex '" re "'.")})
View
@@ -140,6 +140,12 @@
;;; Parsing the .gluer files and building the association library
+;; The following definitions are (partial) regular expression, each yielding one
+;; capture group.
+(def ^:private package-pattern "(?:((?:\\w+\\.)*\\w+)\\.)")
+(def ^:private class-pattern "((?:\\w|\\$)+)")
+(def ^:private member-pattern "(\\w+)")
+
(def rules
"The parse rules for .gluer files."
{; Basic rules
@@ -148,17 +154,17 @@
:where #{ :where-clause-field }
:what #{ :what-clause-new :what-clause-call :what-clause-single}
:using ["using" :class]
- :class #"((\w+\.)*)((\w|\$)+)"
-
+ :class (re-pattern (str package-pattern "?" class-pattern))
+
; Where clauses
:where-clause-field ["field" :field]
- :field #"(\w+\.)+\w+"
+ :field (re-pattern (str package-pattern "?" class-pattern "\\." member-pattern))
; What clauses
:what-clause-new ["new" :class]
:what-clause-call ["call" :method]
- :method #"(\w+\.)+\w+\(.*\)"
+ :method (re-pattern (str package-pattern "?" class-pattern "\\." member-pattern "\\(.*\\)"))
:what-clause-single ["single" :class]})

0 comments on commit 3e377cb

Please sign in to comment.