Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Instaparse使用BNF解析序列化PHP数据_Php_Parsing_Clojure_Bnf_Ebnf - Fatal编程技术网

使用Instaparse使用BNF解析序列化PHP数据

使用Instaparse使用BNF解析序列化PHP数据,php,parsing,clojure,bnf,ebnf,Php,Parsing,Clojure,Bnf,Ebnf,我有一个PHP序列化的值,需要在Clojure中解码。我用这个来反序列化它;它使用EBNF/ABNF符号来定义语法。以下是完整的定义供参考: <S> = expr <expr> = (string | integer | double | boolean | null | array)+ <digit> = #'[0-9]' <number> = negative* (decimal-num | integer-num) <negative&

我有一个PHP序列化的值,需要在Clojure中解码。我用这个来反序列化它;它使用EBNF/ABNF符号来定义语法。以下是完整的定义供参考:

<S> = expr
<expr> = (string | integer | double | boolean | null | array)+
<digit> = #'[0-9]'
<number> = negative* (decimal-num | integer-num)
<negative> = '-'
<integer-num> = digit+
<decimal-num> = integer-num '.' integer-num
<zero-or-one> = '0'|'1'
size = digit+
key = (string | integer)
<val> = expr
array = <'a:'> <size> <':{'> (key val)+ <'}'> <';'>?
boolean = <'b:'> zero-or-one <';'>
null = <'N;'>
integer = <'i:'> number <';'>
double = <'d:'> number <';'>
string = <'s:'> <size> <':\\\"'> #'([^\"]|\\.)*' <'\\\";'>
string = <'s:'> <size> <':\\\"'> #'([^\"]|\\.)*' <'\\\";'>
使用库进行反序列化,当它找到第二个
”时,它会爆炸:

语法定义的这一行存在问题:

<S> = expr
<expr> = (string | integer | double | boolean | null | array)+
<digit> = #'[0-9]'
<number> = negative* (decimal-num | integer-num)
<negative> = '-'
<integer-num> = digit+
<decimal-num> = integer-num '.' integer-num
<zero-or-one> = '0'|'1'
size = digit+
key = (string | integer)
<val> = expr
array = <'a:'> <size> <':{'> (key val)+ <'}'> <';'>?
boolean = <'b:'> zero-or-one <';'>
null = <'N;'>
integer = <'i:'> number <';'>
double = <'d:'> number <';'>
string = <'s:'> <size> <':\\\"'> #'([^\"]|\\.)*' <'\\\";'>
string = <'s:'> <size> <':\\\"'> #'([^\"]|\\.)*' <'\\\";'>
string=#'([^\“]|\\)*'
您会注意到字符串定义不包括
字符。但这不正确,我可以在该字符串中包含任何字符;大小才是关键。我不是BNF专家,所以我正在尝试找出我的选项


是否可以使用大小作为要抓取的正确字符数?如果不可能,是否有人看到我可以调整语法定义以启用正确解析的方法?

我合理地确定,您不能仅使用EBNF解析器编写该语法,因为据我所知,该语法不是上下文无关的。

我认为clos在上下文无关语法中,您可能遇到的最大困难是显式枚举所有预期长度前缀——类似于ABNF:

 string = 's:0:"";' /
          's:1:"' CHAR '";' /
          's:2:"' 2CHAR '";' /
          's:3:"' 3CHAR '";' / ...
如果字符串的长度是有界的,那么这可能会很好地工作,但是对于任意大小的字符串显然不起作用

否则,要正确处理任意长度的字符串,最好的选择可能是手动解析。幸运的是,对于这种大小的语法来说,这应该不是一项太难的任务。

As,这种语法是。尽管如此,它是一种简单的解析方法,只是不需要使用/EBNF。例如,使用:

方便的宏:

(defmacro tagged-sphp-expr [tag parser] 
  `(fn [] (between #(string ~(str tag ":")) #(~parser) #(string ";"))))
其余的:

(def sphp-integer (tagged-sphp-expr "i" integer))

(def sphp-decimal (tagged-sphp-expr "d" decimal))

(defn sphp-boolean [] 
  (= \1 ((tagged-sphp-expr "b" #(chr-in "01")))))

(defn sphp-null [] (string "N;") :null)

(defn sphp-string []
  (let [tag (string "s:")
        size (integer)
        open (no-trim #(string ":\""))
        contents (read-n size)
        close (string "\";")]
    contents))

(declare sphp-array)

(defn sphp-expr [] 
  (any #(sphp-integer) #(sphp-decimal) #(sphp-boolean) #(sphp-null) #(sphp-string) #(sphp-array)))

(defn sphp-key [] 
  (any #(sphp-string) #(sphp-integer)))

(defn sphp-kv-pair [] 
  (apply array-map (series #(sphp-key) #(sphp-expr))))

(defn sphp-array []
  (let [size (between #(string "a:") #(integer) #(string ":{"))
        contents (times size sphp-kv-pair)] 
    (chr \})
    (attempt #(chr \;))
    contents))
测试:

(def test-str "i:1;d:2;s:16:\"{\"key\": \"value\"}\";a:2:{s:3:\"php\";s:3:\"sux\";s:3:\"clj\";s:3:\"rox\";};b:1;")

(println test-str)
;=> i:1;d:2;s:16:"{"key": "value"}";a:2:{s:3:"php";s:3:"sux";s:3:"clj";s:3:"rox";};b:1;

(parse #(multi* sphp-expr) test-str)
;=> [1 2.0 "{\"key\": \"value\"}" [{"php" "sux"} {"clj" "rox"}] true]

我不是BNF方面的专家,但我还没有看到使用表达式中的另一个值定义发生次数的定义。您可能需要一些反向引用,如
string=ANYCHAR*size
-如果不可能,则无法使用BNF解码格式。如果需要,您可能应该使用更通用的格式,如JSON可以。我希望我可以使用JSON。这个应用程序需要在转换期间与PHP应用程序并行工作并共享会话,并且PHP的会话数据是序列化存储的。其他选项,如大修PHP应用程序的会话管理或将解码委托给PHP,都有其自身的规模。好吧,PHP端应该很容易更改。Y您可以定义自定义会话处理程序函数,并且可以以JSON格式存储数据。但您必须确保应用了正确的锁定,否则会出现问题。这也适用于需要锁定文件的替换代码,并使用与PHP兼容的机制来实现。说明了为什么无法使用BNF进行锁定并且提供了一个可行的解决方案;非常感谢!这应该有一天会被清理到一个合适的库中;而不是“N:”;“。此外,当我修复此问题并包含一个null时,我得到了一个解析错误。似乎不允许sphp null返回nil。如果我从nil更改为例如:null,它会工作。parse EZ函数可以将某个东西解析为nil吗?@terjesb感谢您的更正。根据您的评论,我怀疑parse EZ使用了
nil
作为失败,但我没有这样做。”查看它。返回
:null是有意义的,如果需要,可以将结果替换为
nil