While Instaparse is (IMHO) the best parser for use with Clojure, you don't
have to start from such a low level (i.e. parsing a char stream text
file).  Just re-write your original problem a little and you can skip
writing a custom parser.

In Clojure, perhaps the most popular format (certainly the tersest format) is
Hiccup <https://github.com/weavejester/hiccup>.  It is written as a series
of nested vectors, where the *tag* is the first item and any *attributes* are
in a map that is the 2nd item.  We choose the keyword *:value* to label
anything on the right of the equals sign in your original data.  You thus
end up with this:



(def ast-hiccup
  [:HeaderRule {:value :hr-ftp}
    [:Term {:value 100}
      [:name {:value "ftp"}]
      [:From {:value 1}
        [:networkPort {:value "21"}]
        [:Protocol {:value 1}
          [:Tcp {:value 1}]]]
      [:Then {:value 1}
        [:ProtocolInspection {:value 1}
          [:ftpRuleSet {:value "frs-ftp"}]]
        [:ServiceDataFlowId {:value 1}
          [:payload {:value 99}]]]]] )

Using the tupelo.forest library
<http://cloojure.github.io/doc/tupelo/tupelo.forest.html>, we can easily
parse this tree of data and then issue queries on it:


(ns tst.demo.core
  (:use demo.core tupelo.test)
  (:require
    [tupelo.core :as t]
    [tupelo.forest :as tf] ))
(t/refer-tupelo)

(dotest
  (tf/with-forest    (tf/new-forest)
    (let [root-hid   (tf/add-tree-hiccup ast-hiccup)
          tree-1     (tf/hid->tree root-hid)
          bush-1     (tf/hid->bush root-hid)
          >>         (spyx-pretty bush-1)       ; print the AST in "bush"
format (similar to hiccup)

          networkPort-hid     (tf/find-hid root-hid [:** :From :networkPort])
      ; find the :networkPort node
          networkPort-value   (spyx (grab :value (tf/hid->node
networkPort-hid)))   ; extract the :value from it
    ]
      (is= bush-1
        [{:value :hr-ftp, :tag :HeaderRule}
          [{:value 100, :tag :Term}
            [{:value "ftp", :tag :name}]
            [{:value 1, :tag :From}
              [{:value "21", :tag :networkPort}]
              [{:value 1, :tag :Protocol}
                [{:value 1, :tag :Tcp}]]]
            [{:value 1, :tag :Then}
              [{:value 1, :tag :ProtocolInspection}
                [{:value "frs-ftp", :tag :ftpRuleSet}]]
              [{:value 1, :tag :ServiceDataFlowId}
                [{:value 99, :tag :payload}]]]]] )

      (is= networkPort-value "21"))))     ;  verify we found the value "21"

For more examples please see the forest-examples.cljc file
<https://github.com/cloojure/tupelo/blob/master/test/tst/tupelo/forest_examples.cljc>
and the API docs <http://cloojure.github.io/doc/tupelo/tupelo.forest.html>.
More documentation forthcoming.

Enjoy!
Alan



On Tue, Aug 15, 2017 at 7:11 PM, dennis zhuang <killme2...@gmail.com> wrote:

> In my experience, instaparse + defun is a good choice.
>
> https://github.com/Engelberg/instaparse
> https://github.com/killme2008/defun/
>
> 2017-08-15 22:02 GMT+08:00 Gary Trakhman <gary.trakh...@gmail.com>:
>
>> I enjoyed working with clj-antlr recently, it's a wrapper over a java
>> library, but gives you a fast feedback loop with an interpreter instead of
>> generated java code.  The 'clojurey' part is that the output is a nested
>> sequence, from there it's really effective to use tree zippers and
>> core.match to transform the parse-tree into the data structure you need.
>>
>> Take a look at:
>> https://github.com/clojure/core.match
>> https://github.com/aphyr/clj-antlr
>> https://www.ibm.com/developerworks/library/j-treevisit/
>> https://github.com/akhudek/zip-visit
>>
>> On Tue, Aug 15, 2017 at 9:56 AM Laurens Van Houtven <_...@lvh.cc> wrote:
>>
>>> Hi,
>>>
>>>
>>> Instaparse is a great parser generator, especially if you already have a
>>> BNF.
>>>
>>> Sent from my iPhone
>>>
>>> On Aug 15, 2017, at 08:44, sventrax...@gmail.com wrote:
>>>
>>> Thanks for your input. LFE is quite an unexpected "thing".
>>>
>>> What I'm trying to do, is just a "lunch time project"; something that I
>>> can target without corporate constrains just as a learning exercise.
>>> Furthermore I can test the Clojure version against my old working Java
>>> version.
>>>
>>> As I was saying, while experimenting with Instaparse, I'm having the
>>> feeling it is not the correct Clojure tool for this type of development
>>>
>>>
>>>
>>> On Tuesday, August 15, 2017 at 2:17:50 PM UTC+1, adrians wrote:
>>>>
>>>> If you need the features of Erlang but would like that in a Lisp (not
>>>> Common Lisp, though) environment, have you taken a look at LFE (Lisp
>>>> Flavored Erlang)? I'm not trying to discourage you from looking at Clojure,
>>>> but if you need/depend on some of the features of Erlang, LFE might be a
>>>> closer fit.
>>>>
>>>> http://lfe.io
>>>>
>>>> On Tuesday, August 15, 2017 at 8:11:53 AM UTC-4, svent...@gmail.com
>>>> wrote:
>>>>>
>>>>>
>>>>> Hi
>>>>>
>>>>> Months ago I read a review that praised Clojure's clean approach and
>>>>> use of JVM that is almost always available in my deployments.
>>>>>
>>>>> My background: started with 370 assembly ( so I'm not young!!!) and
>>>>> during the last four years I've been using Erlang for network 
>>>>> applications.
>>>>> For my type of work the functional approach, concurrency and bit handling
>>>>> of Erlang are life savings. Nonetheless I feel "the call" of Clojure. As 
>>>>> an
>>>>> exercise I would like to re implement something I did years ago in Java,
>>>>> i.e. a sort of parser. What I have on my hands is a DSL like this
>>>>>
>>>>>             HeaderRule=hr-ftp
>>>>>                Term=100
>>>>>                   name="ftp"
>>>>>                   From=1
>>>>>                      networkPort="21"
>>>>>                      Protocol=1
>>>>>                         Tcp=1
>>>>>                            up
>>>>>                         up
>>>>>                      up
>>>>>                   Then=1
>>>>>                      ProtocolInspection=1
>>>>>                         ftpRuleSet="frs-ftp"
>>>>>                         up
>>>>>                      ServiceDataFlowId=1
>>>>>                         payload=99
>>>>>                         up
>>>>>                      up
>>>>>                   up
>>>>>                up
>>>>>             HeaderRule=hr-http
>>>>>                   ......
>>>>>
>>>>> For my old Java implementation I used state machines to build an
>>>>> internal representation, sort of an AST, that would be used to analyze 
>>>>> pcap
>>>>> files. In my Clojure challenge, I would like to have a different approach.
>>>>> Googling around I've found many options: Parsley, Instaparse, cljcc and
>>>>> more. Some mentioned on www.clojure-toolbox.com seem to be more
>>>>> abandonware.
>>>>> At the moment I'm focusing on Instaparse. However, maybe due to the
>>>>> previous implementation, I feel that this is not the best approach with
>>>>> Clojure. Certainly my rookie state is leading me the wrong way.
>>>>>
>>>>> Comments and feedback will be greatly appreciated
>>>>>
>>>>> Fred
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clojure@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+unsubscr...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to clojure+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clojure@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+unsubscr...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to clojure+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> 庄晓丹
> Email:        killme2...@gmail.com
> Site:           http://fnil.net
>
> 不学习,毋宁死
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to