Java中解析即席if/else语法的推荐策略?

Java中解析即席if/else语法的推荐策略?,java,parsing,grammar,bnf,Java,Parsing,Grammar,Bnf,(抱歉,不确定这里的“特设”一词是否正确……欢迎提出更好的建议) 我试图在Java应用程序中解析Galaxy,以复制(部分)Galaxy软件本身的行为 该格式在命令标记内包含一些“自由文本”if/else子句(AFAIK,这是它们出现的唯一位置): 。。。 sam_to_bam.py --input1=$source.input1 --dbkey=${input1.metadata.dbkey} #如果$source.index_source==“history”: --ref_文件=$sour

(抱歉,不确定这里的“特设”一词是否正确……欢迎提出更好的建议)

我试图在Java应用程序中解析Galaxy,以复制(部分)Galaxy软件本身的行为

该格式在命令标记内包含一些“自由文本”if/else子句(AFAIK,这是它们出现的唯一位置):

。。。
sam_to_bam.py
--input1=$source.input1
--dbkey=${input1.metadata.dbkey}
#如果$source.index_source==“history”:
--ref_文件=$source.ref_文件
#否则
--ref_file=“无”
#如果结束
--output1=$output1
--index_dir=${GALAXY_DATA_index_dir}
...
对于将这个if/else结构解析为可用于在Java中重塑if/else逻辑的内容,建议采用什么策略


BNF/ANTLR是否过了头,最好只是解析成某种对象结构,还是?有适合这里的设计模式吗?(以前并没有使用过BNF/ANTLR,但若值得的话,我愿意进行研究)。

若您想捕获输入的所有结构,解析器是唯一的选择。可以手动地自顶向下递归地编写解析器代码,但这样做没有什么意义,这就是解析器生成器工具存在的原因;使用它们

关于#if#then#else:如果这是您想要捕获的唯一结构,那么您只需要一个非常原始的语法,它还允许包含任意文本的标记将#if#then#else构造之间的粘液作为一个文本块


如果您想要捕获所有的代码结构,并且只允许在某些地方使用条件,那么可以将它们的存在简单地集成到您正在使用的任何BNF中

如果,正如我所怀疑的,这些条件可以发生在任何地方(“特别的”#如果遵循C预处理器风格,并且这些条件可以发生在输入流中的几乎任何地方),那么解析文本并保留条件目前是最先进的解析技术的前沿。这是标准的C-预处理疾病,目前还没有很好的解决方案。在这种情况下,标准解析器生成器无法提供帮助。(手工编码的解析器在这里也不会更好;在这两种情况下都必须使用相同的解决方案)

最近处理这个问题的一个方案(最近几个月刚刚作为博士研究结果报道)是,每当发现一个#if标记来处理#if和#else时,就进行fork解析,并在找到#endif时加入;然后,您需要一种方法来融合到生成的子树,通常作为带有条件的哪个臂标记的不明确子树


如果你想继续你的生活,我建议你坚持这些条件句出现在语法中定义明确的地方,并忍受编写非结构化预处理器指令的人偶尔的抱怨。(“你写了疯狂的代码?对不起,我的工具无法处理它”)。

非常感谢你给出的详细答案!事实上,#if#else东西只出现在标记内部,AFAIK(可能不太清楚)。如前所述,不太确定“ad-hoc”是否是这里的正确术语(对不起,不是英语母语的垃圾邮件作者:s)。。。也许“习惯”更合适。。。嗯……更仔细地看一下您的示例,它显示了用于控制Python代码的预处理器样式的条件。这与使用它们控制C代码的问题完全相同。你必须回答的问题是,“它们是否以结构化的方式使用?”。你可以简单地使用解析器来回答这个问题,解析器会坚持只在你允许的地方接受#if#then#else。啊,好吧。。。如果是这样的话,这也许可以解释为什么我没有在galaxy代码本身中找到解析#If#else语法的代码,尽管我已经浏览了代码。赞成。。。听起来是个不错的选择。:)更新:刚刚从galaxy dev ML了解到,#if#else是python模板语言Cheetah:。。。所以我希望这会增加只在特定地点发生的可能性:)这不是保证。通常,“模板代码生成器”只是使用带有占位符的字符串作为变量点;这使他们能够“生成代码”,而不需要任何理解。我希望这样一个工具,如果它真的处理了条件,允许它们在字符串中的任何位置,因此是非结构化的。你可以一直抱有希望,但我宁愿做一个惊喜的悲观主义者,也不愿做一个惊喜不快的乐观主义者。
...
<command interpreter="python">
  sam_to_bam.py
    --input1=$source.input1
    --dbkey=${input1.metadata.dbkey} 
    #if $source.index_source == "history":
      --ref_file=$source.ref_file
    #else
      --ref_file="None"
    #end if
    --output1=$output1
    --index_dir=${GALAXY_DATA_INDEX_DIR}
</command>
...