Parsing dypgen中的模式匹配
我想处理dypgen中的一些歧义。我在手册中找到了一些东西,我想知道我如何使用它。 在手册第5.2点“符号上的模式匹配”中,有一个示例:Parsing dypgen中的模式匹配,parsing,ocaml,lexical-analysis,ambiguity,Parsing,Ocaml,Lexical Analysis,Ambiguity,我想处理dypgen中的一些歧义。我在手册中找到了一些东西,我想知道我如何使用它。 在手册第5.2点“符号上的模式匹配”中,有一个示例: expr: | expr OP<"+"> expr { $1 + $2 } | expr OP<"*"> expr { $1 * $2 } forest.ml现在具有以下打印功能: let print_forest forest = let rec aux1 t = match t with | Word x -&
expr:
| expr OP<"+"> expr { $1 + $2 }
| expr OP<"*"> expr { $1 * $2 }
forest.ml现在具有以下打印功能:
let print_forest forest =
let rec aux1 t = match t with
| Word x
-> print_string x
| Noun (x) -> (
print_string "N [";
aux1 x;
print_string " ]")
| Sg (x) -> (
print_string "Sg [";
aux1 x;
print_string " ]")
| Pl (x) -> (
print_string "Pl [";
aux1 x;
print_string " ]")
in
let aux2 t = aux1 t; print_newline () in
List.iter aux2 forest;
print_newline ()
parser_tree.mli包含:
{
open Parse_tree
let dyp_merge = Dyp.keep_all
}
%start main
%layout [' ' '\t']
%%
main : np "." "\n" { $1 }
np:
| sg {Noun($1)}
| pl {Noun($1)}
sg: word <Word("sheep"|"fish")> {Sg($1)}
sg: word <Word("cat"|"dog")> {Sg($1)}
pl: word <Word("sheep"|"fish")> {Pl($1)}
pl: word <Word("cats"|"dogs")> {Pl($1)}
/* OR try:
sg: word <printf> {Sg($1)}
pl: word <printf> {Pl($1)}
*/
word:
| (['A'-'Z' 'a'-'z']+) {Word($1)}
type tree =
| Word of string
| Noun of tree
| Sg of tree
| Pl of tree
然后你可以确定鱼、羊、猫等的数字
sheep or fish can be singular and plural. cats and dogs cannot.
fish.
N [Sg [fish ] ]
N [Pl [fish ] ]
我对戴普根一无所知,所以我想弄明白 让我们看看我发现了什么 在parser.dyp文件中,可以定义lexer和解析器,也可以使用外部lexer。以下是我所做的: 我的ast如下所示: parse_prog.mli
type f =
| Print of string
| Function of string list * string * string
type program = f list
prog_parser.dyp
{
open Parse_prog
(* let dyp_merge = Dyp.keep_all *)
let string_buf = Buffer.create 10
}
%start main
%relation pf<pr
%lexer
let newline = '\n'
let space = [' ' '\t' '\r']
let uident = ['A'-'Z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
let lident = ['a'-'z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
rule string = parse
| '"' { () }
| _ { Buffer.add_string string_buf (Dyp.lexeme lexbuf);
string lexbuf }
main lexer =
newline | space + -> { () }
"fun" -> ANONYMFUNCTION { () }
lident -> FUNCTION { Dyp.lexeme lexbuf }
uident -> MODULE { Dyp.lexeme lexbuf }
'"' -> STRING { Buffer.clear string_buf;
string lexbuf;
Buffer.contents string_buf }
%parser
main : function_calls eof
{ $1 }
function_calls:
|
{ [] }
| function_call ";" function_calls
{ $1 :: $3 }
function_call:
| printf STRING
{ Print $2 } pr
| "(" ANONYMFUNCTION lident "->" printf lident ")" STRING
{ Print $6 } pf
| nested_modules "." FUNCTION STRING
{ Function ($1, $3, $4) } pf
| FUNCTION STRING
{ Function ([], $1, $2) } pf
| "(" ANONYMFUNCTION lident "->" FUNCTION lident ")" STRING
{ Function ([], $5, $8) } pf
printf:
| FUNCTION<"printf">
{ () }
| MODULE<"Printf"> "." FUNCTION<"printf">
{ () }
nested_modules:
| MODULE
{ [$1] }
| MODULE "." nested_modules
{ $1 :: $3 }
例如,对于以下文件:
测试
printf "first print";
Printf.printf "nested print";
Format.eprintf "nothing possible";
(fun x -> printf x) "Anonymous print";
如果我执行/myexec test
,我将得到以下提示
You want to print : first print
You want to print : nested print
I can't do anything with Format.eprintf("nothing possible")
You want to print : x
------------
所以,TL;DR,这里的手动示例只是为了向您展示,您可以使用已定义的令牌(我从未定义过令牌打印,只是功能)并匹配它们以获得新规则
我希望这是清楚的,我从你的问题中学到了很多;-)
[EDIT]因此,我更改了解析器以匹配您想要观看的内容:
{
open Parse_prog
(* let dyp_merge = Dyp.keep_all *)
let string_buf = Buffer.create 10
}
%start main
%relation pf<pp
%lexer
let newline = '\n'
let space = [' ' '\t' '\r']
let uident = ['A'-'Z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
let lident = ['a'-'z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
rule string = parse
| '"' { () }
| _ { Buffer.add_string string_buf (Dyp.lexeme lexbuf);
string lexbuf }
main lexer =
newline | space + -> { () }
"fun" -> ANONYMFUNCTION { () }
lident -> FUNCTION { Dyp.lexeme lexbuf }
uident -> MODULE { Dyp.lexeme lexbuf }
'"' -> STRING { Buffer.clear string_buf;
string lexbuf;
Buffer.contents string_buf }
%parser
main : function_calls eof
{ $1 }
function_calls:
|
{ [] } pf
| function_call <Function((["Printf"] | []), "printf", st)> ";" function_calls
{ (Print st) :: $3 } pp
| function_call ";" function_calls
{ $1 :: $3 } pf
function_call:
| nested_modules "." FUNCTION STRING
{ Function ($1, $3, $4) }
| FUNCTION STRING
{ Function ([], $1, $2) }
| "(" ANONYMFUNCTION lident "->" FUNCTION lident ")" STRING
{ Function ([], $5, $8) }
nested_modules:
| MODULE
{ [$1] }
| MODULE "." nested_modules
{ $1 :: $3 }
{
打开解析程序
(*让dyp_合并=dyp.keep_all*)
让string_buf=Buffer.create 10
}
%起动总管
%关系pf{()}
“fun”->匿名函数{()}
lident->FUNCTION{Dyp.lexeme-lexbuf}
uident->MODULE{Dyp.lexeme-lexbuf}
“''->STRING{Buffer.clear STRING_buf;
字符串lexbuf;
Buffer.contents字符串_buf}
%分析器
main:函数_调用eof
{ $1 }
函数调用:
|
{[]}pf
|功能调用”;“函数调用”
{(正版):$3}页
|功能调用”;“函数调用”
{$1::$3}pf
函数调用:
|嵌套的_模块“.”函数字符串
{函数($1,$3,$4)}
|函数字符串
{函数([],$1,$2)}
|“(“匿名函数lident”->“函数lident”)”字符串
{函数([],$5,$8)}
嵌套的\u模块:
|模块
{ [$1] }
|模块“.”嵌套的_模块
{ $1 :: $3 }
在这里,正如您所看到的,我在解析函数时并没有处理函数是打印的这一事实,而是在我将其放入函数列表时处理的。因此,我匹配了由我的解析器构建的
代数类型。
。我希望这个示例对您来说是可以的;-)(但请注意,这是非常不明确的!:-D)如何解析函数?我使用dypgen的演示作为起点,并使用它们的makefile…语法在.dyp文件中,它确实:.dyp.ml:path_to_dypgen$You want to print : first print
You want to print : nested print
I can't do anything with Format.eprintf("nothing possible")
You want to print : x
------------
{
open Parse_prog
(* let dyp_merge = Dyp.keep_all *)
let string_buf = Buffer.create 10
}
%start main
%relation pf<pp
%lexer
let newline = '\n'
let space = [' ' '\t' '\r']
let uident = ['A'-'Z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
let lident = ['a'-'z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
rule string = parse
| '"' { () }
| _ { Buffer.add_string string_buf (Dyp.lexeme lexbuf);
string lexbuf }
main lexer =
newline | space + -> { () }
"fun" -> ANONYMFUNCTION { () }
lident -> FUNCTION { Dyp.lexeme lexbuf }
uident -> MODULE { Dyp.lexeme lexbuf }
'"' -> STRING { Buffer.clear string_buf;
string lexbuf;
Buffer.contents string_buf }
%parser
main : function_calls eof
{ $1 }
function_calls:
|
{ [] } pf
| function_call <Function((["Printf"] | []), "printf", st)> ";" function_calls
{ (Print st) :: $3 } pp
| function_call ";" function_calls
{ $1 :: $3 } pf
function_call:
| nested_modules "." FUNCTION STRING
{ Function ($1, $3, $4) }
| FUNCTION STRING
{ Function ([], $1, $2) }
| "(" ANONYMFUNCTION lident "->" FUNCTION lident ")" STRING
{ Function ([], $5, $8) }
nested_modules:
| MODULE
{ [$1] }
| MODULE "." nested_modules
{ $1 :: $3 }