我想解析AppleSoft Basic脚本中的一些数据。我选择ANTLR并下载以下语法:jvmBasic
我试图提取没有参数的函数名:
return parser.prog().line(0).amprstmt(0).statement().getText();但是它返回打印“HELLO”,例如完全表达式,但这里的行号是我想解析的字符串:
10打印“你好!”
发布于 2016-07-07 00:09:26
我认为这个问题实际上取决于您的ANTLR程序的实现,但是如果您使用的是一个树用户/侦听器,那么您可能希望针对特定标记的规则,而不是整个循环的“语句”规则,它包含许多类型的语句:
//each line can have one to many amprstmt's
line
: (linenumber ((amprstmt (COLON amprstmt?)*) | (COMMENT | REM)))
;
amprstmt
: (amperoper? statement) //encounters a statement here
| (COMMENT | REM)
;
//statements can be made of 1 to many sub statements
statement
: (CLS | LOAD | SAVE | TRACE | NOTRACE | FLASH | INVERSE | GR | NORMAL | SHLOAD | CLEAR | RUN | STOP | TEXT | HOME | HGR | HGR2)
| prstmt
| printstmt1 //the print rule
//MANY MANY OTHER RULES HERE TOO LONG TO PASTE........
;
//the example rule that occurs when the token's "print" is encountered
printstmt1
: (PRINT | QUESTION) printlist?
;
printlist
: expression (COMMA | SEMICOLON)? printlist*
;从BNF类型语法中可以看到,此语法中的语句规则包括打印语句的规则以及所有其他类型的语句,因此它将包含10、print和hello,并随后在遇到其中任何一个语句时,使用getText()方法返回文本,但行号除外,这是语句规则之外的规则。
如果您希望针对这些特定规则来处理遇到这些规则时所发生的事情,那么您很可能希望通过扩展jvmBasiListener类来为每个规则添加功能,如所示这里所示。
示例:
-jvmBasicListener.java
-extended to jvmBasicCustomListener.java
void enterPrintstmt1(jvmBasicParser.Printstmt1Context ctx){
System.out.println(ctx.getText());
}但是,如果所有这些都是安装的,并且您只是希望使用单行返回字符串值等,那么您就可以通过寻址语句的子节点来访问较低级别的方法,这样就可以使用amprstmt->语句->printstmt1 1->值:
return parser.prog().line().amprstmt(0).statement().printstmt1().getText();为了稍微缩小我的回答范围,专门针对您输入的"10打印“"HELLO”的规则是:
linenumber (contains Number) , statement->printstmt1 and statement->datastmt->datum (contains STRINGLITERAL)因此,正如上面所示,linenumber规则本身就存在,而定义文本的其他2个规则是语句的子规则,这解释了在获取语句规则文本时输出除行号以外的所有内容。
解决这些问题并使用getText()而不是语句之类的包含性规则可能会给出您想要的结果。
我将更新以解决您的问题,因为答案可能会稍长一些,在我看来,处理特定规则而不是生成侦听器或访问者的最简单方法是在语法文件规则中实现以下操作:
printstmt1
: (PRINT | QUESTION) printlist? {System.out.println("Print"); //your java code }
;这将只允许您处理每条规则,并执行您希望执行的任何java操作。然后,您可以简单地编译代码,如下所示:
java -jar antlr-4.5.3-complete.jar jvmBasic.g4 -visitor在此之后,您可以简单地运行您希望的代码,下面是一个示例:
import JVM1.jvmBasicLexer;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
public class Jvm extends jvmBasicBaseVisitor<Object> {
public static void main(String[] args) {
jvmBasicLexer lexer = new jvmBasicLexer(new ANTLRInputStream("10 PRINT \"Hello!\""));
jvmBasicParser parser = new jvmBasicParser(new CommonTokenStream(lexer));
ParseTree tree = parser.prog();
}
}然后,该示例的输出将是公正的:
Print您还可以将您喜欢的任何Java方法合并到语法中,以解决遇到的每条规则,或者开发您自己的类和方法来处理它,或者直接打印出结果。
更新
现在只想回答最新的问题:parser.line().linenumber().getText() -表示行号,因为行不是语句的一部分。
parser.prog().line(0).amprstmt(0).statement().printstmt1().PRINT().getText() -由于打印是在printstmt1中隔离的,所以在规则中不包括CLR。
parser.prog().line(0).amprstmt(0).statement().printstmt1().printlist().expression().getText() -获得值"hello“,因为它是包含在printstmt1规则中的表达式的一部分。
*祝你好运
https://stackoverflow.com/questions/38232989
复制相似问题