有人可以帮助我使用上下文无关文法。到目前为止,我一直使用正则表达式从字符串中删除注释,阻止注释和空行,以便可以将其用于计算PLOC。这似乎非常慢,所以我正在寻找其他更有效的方法。
我看到以下帖子:What is the best way to ignore comments in a java file with Rascal?
我不知道如何使用它,帮助也使我无法理解。当我尝试定义帖子中使用的行时,我立即收到错误消息。
lexical SingleLineComment = "//" ~[\n] "\n";
有人可以帮我解决这个问题,并解释一下如何设置这种上下文无关的语法,然后实际提取所需的数据吗?
亲切的问候,
鲍勃
首先这会有所帮助:Rascal CFG表示法中的~
不在语言中,字符类的否定像这样编写:![\n]
。
要在Rascal中使用无上下文语法,需要三个步骤:
使用它来解析输入,例如:
//这是基本的parse命令,但是请注意,它在TopNonTerminal文本之前和之后将不接受空格和换行符:Prog myParseTree = parse(#Prog,“示例字符串”);
//您可以直接对输入文件执行相同操作:Prog myParseTree = parse(#TopNonTerminal,| home:///myProgram.func |);
//如果需要在程序之前和之后接受布局,请使用“开始非终端”:start [Prog] myParseTree = parse(#start [TopNonTerminal],| home:///myProgram.func |);编程序myProgram = myParseTree.top;
//解析内容的简写:myProgram = [Prog]“ example”;myProgram = [编] | home:///myLocation.txt |;
一旦有了树,就可以开始使用visit
和/
深度匹配从树中提取信息,或者根据需要编写递归函数。可以在以下示例中找到示例:http://docs.rascal-mpl.org/unstable/Recipes/#Languages-Func,但是这里还有一些常见的习语,还可以从解析树中提取信息:
//生成树中每个节点的源位置:myParseTree @ \ loc
//产生一组所有Stat类型的节点{s | / Stat s:= myParseTree}
//模式匹配if-then-else并绑定这三个表达式并将它们收集在一个集合中:{e1,e2,e3 | (统计)if <Exp e1> then <Exp e2> else Exp end
//收集所有子树的所有位置(每个解析树都是非终端类型的,它是Tree
的子类型。它对小的子树使用| unknown:/// |),出于效率考虑,没有被注释,例如文字和字符类:[t @ \ loc?|未知:/// | | /树t:= myParseTree]
那应该给您一个开始。我会尝试一些东西,并查看更多示例。编写语法是一件不错的事情,但是它确实需要一些反复试验的方法,例如编写正则表达式,但更多的是。
对于您可能正在编写的语法,该语法可以找到源代码注释,但将其余部分保留为“任何字符”,您将需要使用最长的匹配歧义词很多:
lexical Identifier = [a-z]+ !>> [a-z]; // means do not accept an Identifier if there is still [a-z] to add to it; so only the longest possible Identifier will match.
这种无上下文关联的语法被喻为“海岛语法”,因为您将为要识别的部分(注释为“海岛”)编写精确的规则,而其余部分则保持不变(其余部分为“水”)。参见https://dl.acm.org/citation.cfm?id=837160