编写解析语法的解析器,然后从解析树转换为所需的符号。
转换本身相当简单:
- 将“#”评论介绍人替换为“//”
- 将 ':' 标记替换为 '::='
- 用 '(' 替换 '[' 标记
- 将“]”标记替换为“)?”
一个合适的元语法,在W3C notation,是
Grammar ::= Rule+ EOF
Rule ::= Nonterminal ':' Alternatives
Alternatives
::= Alternative ( '|' Alternative )*
Alternative
::= ( Symbol ( '*' | '+' )? )*
Symbol ::= Nonterminal
| Terminal
| '(' Alternatives ')'
| '[' Alternatives ']'
<?TOKENS?>
Nonterminal
::= [a-z] [a-z_]*
Terminal ::= [A-Z] [A-Z_]*
| "'" [^']+ "'"
EOF ::= $
IgnorableWhitespace
::= [ #x9#xA#xD]+
| '#' [^#xA]* [#xA]
/* ws: definition */
将其放入grammar.ebnf,然后使用REx为其创建解析器,编码例如在XQuery,使用这个命令行:
-xquery -tree
这将为您提供 XQuery 模块 grammar.xquery。接下来,把python语法放到python.grammar,这个XQuery程序放到transform.xquery:
import module namespace p="grammar" at "grammar.xquery";
declare option saxon:output "method=text";
declare variable $input as xs:string external;
for $token in p:parse-Grammar(unparsed-text($input))//text()
return
if (starts-with(normalize-space($token), "#")) then
replace($token, "((^|
)[\s])*#", "$1//")
else
switch ($token)
case ":" return "::="
case "[" return "("
case "]" return ")?"
default return $token
然后使用Saxon 运行它:
java net.sf.saxon.Query transform.xquery input=python.grammar > python.ebnf
结果就是你想要的。
当然,您也可以使用您喜欢的文本编辑器仔细地进行全局替换,以达到同样的效果。做对了会更有趣。