【发布时间】:2016-09-15 11:36:37
【问题描述】:
我想知道,如果这是一个错误或行为,那是发明者的意图。
这里我有一个 dypgen 语法的最小示例:
{
open Parse_tree
let dyp_merge = Dyp.keep_all
}
%start main
%layout [' ' '\t']
%%
main:
| a "\n" { $1 }
a:
| ms b { Mt ($1,$2) }
| b <Mt(_,_)> kon1 b { Koo ($1, $2, $3) }
| b <Mt(_,_)> kon2 b { Koo ($1, $2, $3) }
| b { $1 }
b:
| k { $1 }
| ns b { Nt ($1,$2) }
/* If you comment this line out, it will work with the permutation, but I need the 'n' ! */
/* | b <Nt(_,_)> kon1 b { Koo ($1, $2, $3) }
| b <Nt(_,_)> kon2 b { Koo ($1, $2, $3) }*/
k:
| k kon1 k { Koo ($1, $2, $3) }
| k kon2 k { Koo ($1, $2, $3) }
| ks { $1 }
ms:
| words <M(_)> { $1 }
ns:
| words <N(_)> { $1 }
ks:
| words <K(_)> { $1 }
kon1:
| words <U(_)> { $1 }
kon2:
| 'y' { Y($1) }
words:
| chain { $1 }
throw_away:
| word "|" throw_away { $3 }
| word { $1 }
chain:
| word "|" throw_away { $1 }
| word "|" chain { $3 }
| word { $1 }
word:
| ('m' ['1'-'9']?) { M ($1) }
| ('n' ['1'-'9']?) { N ($1) }
| ('K' ['1'-'9']?) { K ($1) }
| ('u' ['1'-'9']?) { U ($1) }
这个例子可以处理这样的语法:
想想 ?和 * 作为正则表达式运算符,'s' 和 'm' 和 'K' 作为词法。
s = m? n* K
“K”、“m”和“n”也可以替换为这些字母和后面的 1-9 之间的数字 或者它们可以替换为由“|”分隔的列表作为
m1
n1|n2
K|K|K or K1|K2|K3
这些列表也可以混合为
m1|n1|K1
所有这些列表都被解析为可能的歧义,它们被全局合并——在 dypgen 的已知意义上——与
let dyp_merge = Dyp.keep_all
如果你输入:
m1|n1|K1 m1|n1|K1 m1|n1|K1
你得到结果:
m1 > n1 > K1 n1 > n1 > K1
如果你输入
K1|K2
你得到
K1 K2
现在有趣的一点: 在语法中还有另一个特点。在自然语言的风格中,有一个带有“u”或“y”的“协调绑定”。
这可以将这些“短语”列表(一个带有可选前置“m”和可选数字“n”的“K”字母)绑定到“K1 和 K2”之类的东西。 语法可以解析:
K1|K2 u K3|K4
K1|K2 y K3|K4
正如我所想,它应该有相同的结果。 但是“协调绑定”之间的区别是: lexem 'u' 被定义为歧义列表,其方式与 m、n、K 相同,也可以与 'K's、'm's、'n's 混合 lexem 'y' 是在没有这个列表元素的情况下定义的。
这产生了(令人惊讶的)不同:
K1|K2 u K3|K4
被解析为:
koo { K1 u K4 } koo { K2 u K4 }
和
K1|K2 y K3|K4
被解析为:
koo2 { K1 y K3 } koo2 { K2 y K3 } koo2 { K1 y K4 } koo2 { K2 y K4 }
在第一种情况下,u 坐标的第二部分没有置换。 在第二种情况下,协调的第二部分被置换(因为 dypgen 通常会产生歧义)。
为什么会有所不同?
(它必须以某种方式连接到 m's 和 n's,因为如果 'n's 的规则被忽略,它就可以工作。)
最好的问候,并感谢您考虑
gwf
最小的例子是 dypgen-demos 的风格,尝试在演示中创建一个文件夹“abc”并将所有提到的、完全引用的文件放在那里。 “parse_tree”:
type tree =
| M of string
| Mt of tree * tree
| N of string
| Nt of tree * tree
| K of string
| U of string
| Y of string
| Koo of tree * tree * tree
| Koo2 of tree * tree * tree * tree
一个文件“printit.ml”: 打开 Parse_tree
let print_abc abc=
let rec aux1 t = match t with
| Koo(x1, k, x2) -> (
print_string "\x1b[1m\x1b[31mkoo {\x1b[21m\027[0m ";
aux1 x1;
print_string "";
aux1 k;
print_string "";
aux1 x2;
print_string "\x1b[1m\x1b[31m}\x1b[21m\027[0m")
| Koo2(k1, x1, k2, x2) -> (
print_string "\x1b[1m\x1b[31mkoo2 {\x1b[21m\027[0m ";
aux1 k1;
print_string " ";
aux1 x1;
print_string "";
aux1 k2;
print_string "";
aux1 x2;
print_string "\x1b[1m\x1b[31m}\x1b[21m\027[0m")
| Word (w) -> print_string (w ^ " ")
| M (w) -> print_string (w ^ " ")
| K (w) -> print_string (w ^ " ")
| N (w) -> print_string (w ^ " ")
| U (w) -> print_string (w ^ " ")
| Y (w) -> print_string (w ^ " ")
| Nt (p, l)
| Mt (p, l) -> (
print_string "";
aux1 p;
print_string " > ";
aux1 l;)
in
let aux2 t = aux1 t; print_newline () in
List.iter aux2 abc
和“主”程序: 打开 Parse_tree 打开 Printit
let () = print_endline "
please try:
K1|K2 u K3|K4
and
K1|K2 y K3|K4
"
let lexbuf = Dyp.from_channel (Abc_parser.pp ()) stdin
let _ =
try
while true do
(Dyp.flush_input lexbuf;
try
let pf = Abc_parser.main lexbuf in
print_abc (List.map (fun (x,_) -> x) pf)
with
Dyp.Syntax_error -> Printf.printf "Syntax error\n\n"
);
flush stdout
done
with Failure _ -> exit 0
和“Makefile”
SOURCES = printit.ml abc_parser.dyp abc.ml
REP = -I ../../dyplib
CAMLC = ocamlc $(REP)
DYPGEN = ../../dypgen/dypgen --ocamlc "-I ../../dyplib"
LIBS=dyp.cma
all: abc
SOURCES1 = $(SOURCES:.mll=.ml)
SOURCES2 = $(SOURCES1:.dyp=.ml)
OBJS = $(SOURCES2:.ml=.cmo)
abc: parse_tree.cmi $(OBJS)
$(CAMLC) -o abc $(LIBS) $(OBJS)
.SUFFIXES: .ml .mli .cmo .cmi .dyp
.ml.cmo:
$(CAMLC) -c $<
.mli.cmi:
$(CAMLC) -c $<
.dyp.ml:
$(DYPGEN) $<
$(CAMLC) -c $*.mli
clean:
rm -f *.cm[iox] *~ .*~ *.o
rm -f abc
rm -f *.extract_type *_temp.ml
rm -f *parser.ml *parser.mli
【问题讨论】:
-
我编辑了我的重要文本行。我在输出的描述中混淆了'u'和'y':“K1|K2 y K3|K4” -> koo { K1 y K3 }, koo { K2 y K3 }, koo { K1 y K4 }, koo { K2 y K4 } 和 "K1|K2 u K3|K4" -> koo { K1 u K4 }, koo { K2 u K4 }
标签: parsing nlp ocaml lexer ambiguity