使用amotoen解决问题

时间:2012-08-15 13:39:54

标签: parsing clojure peg

我正在尝试编写一个语法来解析一个简单的语言来描述鼓循环,使用Clojure和amotoen。语言如下: -

# Test Loop
# this is a comment

BPM: 100

Samples:
 BD: bd.wav
 SD: sd.wav
CHH: chh.wav
CSH: csh.wav

Body:
 BD: /---/---/---/---
 SD: ---/--/--/-/--/-
CHH: --/---/---/---/-
CSH: /---------------

# this is another comment

我已经将语法定义如下: -

(def g {
        :Whitespace '(| \space \newline \tab \, :Comment)
        :_* '(* :Whitespace)
        :_ [:Whitespace '(* :Whitespace)]
        :Comment [\# '(* (% \newline)) \newline]
        :BPM [\B \P \M \: :_* '(* :Number) \newline]
        :Number '(* :Digit)
        :Digit (a/lpegs '| "0123456789")
        :Samples [\S \a \m \p \l \e \s \: \newline '(* :SampleDef)]
        :SampleDef [:_* :Name \: :_* :File \newline]
        :Name '(* (% \:))
        :File '(* (% \newline))
        :Body [\B \o \d \y \: \newline '(* :Pattern)]
        :Pattern [:_* :Name \: :_* '(* (| \/ \-)) '(| \newline \$)]
        :Document [:_* :BPM :_* :Samples :_* :Body :_* \$]
       })

当我单独在示例文件的每个部分上调用pegasus时,它们会被正确解析。例如: -

(pprint
  (a/pegasus
    :Body
    g
    (a/wrap-string
      "Body:\n
        BD: /---/---/---/---\n
        SD: ---/--/--/-/--/-\n
       CHH: --/---/---/---/-\n
       CSH: /---------------\n")))

但是,当我致电(pprint (a/pegasus :Document g (a/wrap-string (slurp "sample.orc"))))时,我得到的只是nil。同样,如果我将(a/wrap-string (slurp "sample.orc"))替换为包含sample.orc中包含的文本的字符串。

所以,我的问题是:有人能发现我的语法有什么问题吗?我完全没有想法,现在我已经盯着它看了几天。我确信这是一件令人尴尬的事情,但我看不到它!

提前致谢。

1 个答案:

答案 0 :(得分:4)

:Samples规则使用:Body:File可以为空,输入结尾应标记为:$而不是\$。这是一个修正过的语法:

(def g                                                                                                                                                                  
  {                                                                                                                                                                     
   :Whitespace '(| \space \tab \, :Comment)                                                                                                                             
   :n* '(* (| \newline :Comment))                                                                                                                                       
   :_* '(* :Whitespace)                                                                                                                                                 
   :_ [:Whitespace '(* :Whitespace)]                                                                                                                                    
   :Comment [\# '(* (% \newline)) \newline]                                                                                                                             
   :BPM [\B \P \M \: :_* '(* :Number) \newline]                                                                                                                         
   :Number '(* :Digit)                                                                                                                                                  
   :Digit (a/lpegs '| "0123456789")                                                                                                                                     
   :Samples [\S \a \m \p \l \e \s \: \newline '(* :SampleDef)]                                                                                                          
   :SampleDef [:_* :Name \: :_* :File \newline]                                                                                                                         
   :Name '[(% \:) (* (% \:))]                                                                                                                                           
   :File '[(% \newline) (* (% \newline))]                                                                                                                               
   :Body [\B \o \d \y \: \newline '(* :Pattern)]                                                                                                                        
   :Pattern [:_* :Name \: :_* '(* (| \/ \-)) '(| \newline :$)]                                                                                                          
   :Document [:n* :BPM :n* :Samples :n* :Body :n* :$]                                                                                                                   
   })

;; sample.orc contains the example input from the question text
(pprint (a/pegasus :Document g (a/wrap-string (slurp "sample.orc"))))

;; output:
{:Document
 [{:n*
   ({:Comment [\# (\space \T \e \s \t \space \L \o \o \p) \newline]}
    {:Comment
     [\#
      (\space
       \t
       \h
       \i
       \s
       \space
       \i
       \s
       \space
       \a
       \space
       \c
       \o
       \m
       \m
       \e
       \n
       \t)
      \newline]}
    \newline)}
  {:BPM
   [\B
    \P
    \M
    \:
    {:_* {:Whitespace \space}}
    {:Number ({:Digit \1} {:Digit \0} {:Digit \0})}
    \newline]}
  {:n* \newline}
  {:Samples
   [\S
    \a
    \m
    \p
    \l
    \e
    \s
    \:
    \newline
    ({:SampleDef
      [{:_* {:Whitespace \space}}
       {:Name [\B \D]}
       \:
       {:_* {:Whitespace \space}}
       {:File [\b (\d \. \w \a \v)]}
       \newline]}
     {:SampleDef
      [{:_* {:Whitespace \space}}
       {:Name [\S \D]}
       \:
       {:_* {:Whitespace \space}}
       {:File [\s (\d \. \w \a \v)]}
       \newline]}
     {:SampleDef
      [{:_* ()}
       {:Name [\C (\H \H)]}
       \:
       {:_* {:Whitespace \space}}
       {:File [\c (\h \h \. \w \a \v)]}
       \newline]}
     {:SampleDef
      [{:_* ()}
       {:Name [\C (\S \H)]}
       \:
       {:_* {:Whitespace \space}}
       {:File [\c (\s \h \. \w \a \v)]}
       \newline]})]}
  {:n* \newline}
  {:Body
   [\B
    \o
    \d
    \y
    \:
    \newline
    ({:Pattern
      [{:_* {:Whitespace \space}}
       {:Name [\B \D]}
       \:
       {:_* {:Whitespace \space}}
       (\/ \- \- \- \/ \- \- \- \/ \- \- \- \/ \- \- \-)
       \newline]}
     {:Pattern
      [{:_* {:Whitespace \space}}
       {:Name [\S \D]}
       \:
       {:_* {:Whitespace \space}}
       (\- \- \- \/ \- \- \/ \- \- \/ \- \/ \- \- \/ \-)
       \newline]}
     {:Pattern
      [{:_* ()}
       {:Name [\C (\H \H)]}
       \:
       {:_* {:Whitespace \space}}
       (\- \- \/ \- \- \- \/ \- \- \- \/ \- \- \- \/ \-)
       \newline]}
     {:Pattern
      [{:_* ()}
       {:Name [\C (\S \H)]}
       \:
       {:_* {:Whitespace \space}}
       (\/ \- \- \- \- \- \- \- \- \- \- \- \- \- \- \-)
       \newline]})]}
  {:n*
   (\newline
    {:Comment
     [\#
      (\space
       \t
       \h
       \i
       \s
       \space
       \i
       \s
       \space
       \a
       \n
       \o
       \t
       \h
       \e
       \r
       \space
       \c
       \o
       \m
       \m
       \e
       \n
       \t)
      \newline]})}
  :$]}