当前位置: 首页 > 知识库问答 >
问题:

用ANTLR4、C#和VS2017编写自定义解析器

濮阳振海
2023-03-14

我试图解析具有如下格式的文件。我想要做的是创建几个var和一个结构数组来包含关于文件的信息。例如,(pseudocode)int atomNumber=27,然后是string struct[0].element=c&float struct[0].x=0.6877350。我需要一个解析器/脚本,允许我从文件中获得这些信息。我试图用ANTLR/自定义解析器而不是Regex来实现这一点,因为其中一些文件变得很大;我是在Unity中这样做的,Regex的速度很慢,因为它影响了Unity的垃圾收集。然而,我是使用ANTLR的新手,所以我很难让它发挥作用。

下面是文件结构的一个示例:

27
 comment 
C 0.6877350 0.0715370 -1.2710340
C 0.0387890 -0.2132770 2.4629140
C 2.9026270 0.7676750 -0.4325690
C 1.9897370 0.2682320 -1.4699130
H 3.8932221 0.3135170 -0.4057700
H 2.3979900 0.0407470 -2.4529259
H 0.0607820 -1.2602330 2.1661179
H 0.1969520 0.2155350 -0.3100010
O -0.1311780 -0.2708320 -2.3204310
C -1.0381711 -1.2940150 -2.2029400
O -1.8197130 -1.4577920 -3.0971811
C -0.9588580 -2.1451390 -0.9617850
H 0.0764330 -2.4116330 -0.7270430
H -1.5478179 -3.0458710 -1.1361990
H -1.3813020 -1.6050299 -0.1051530
C 1.0799000 0.3532050 3.0701120
H 1.9819210 -0.2100150 3.2911880
H 1.0789630 1.4006370 3.3635521
C 2.6065600 1.7304400 0.4415480
H 3.3160350 2.0450499 1.2023780
H 1.6531780 2.2537251 0.4046360
C -1.2067200 0.5084640 2.0837281
C -1.4050720 1.9360650 2.5400000
H -0.6525800 2.5874960 2.0799990
H -2.3981910 2.2678981 2.2341671
H -1.3007090 2.0248840 3.6260951
O -2.0373070 -0.0501320 1.3878731
27
 comment 
C 0.6835910 0.0801290 -1.2651600
C 0.0385760 -0.2142480 2.4595370
C 2.9039860 0.7584860 -0.4261270
C 1.9882360 0.2606780 -1.4617670
H 3.8887999 0.2924340 -0.3916030
H 2.3965650 0.0209800 -2.4418731
H 0.0600150 -1.2637050 2.1717429
H 0.1919770 0.2365210 -0.3064940
O -0.1368310 -0.2607420 -2.3141041
C -1.0378500 -1.2895941 -2.1994519
O -1.8194150 -1.4546410 -3.0934210
C -0.9520160 -2.1443820 -0.9613080
H 0.0850850 -2.4055369 -0.7287190
H -1.5361210 -3.0478990 -1.1376450
H -1.3763330 -1.6092030 -0.1024920
C 1.0823750 0.3586390 3.0560379
H 1.9862601 -0.2015870 3.2770901
H 1.0818750 1.4086040 3.3402641
C 2.6171989 1.7337860 0.4371280
H 3.3282030 2.0474880 1.1969039
H 1.6705470 2.2685010 0.3915880
C -1.2096530 0.5029830 2.0807769
C -1.4067100 1.9345620 2.5251229
H -0.6585890 2.5824180 2.0530601
H -2.4025259 2.2620981 2.2234540
H -1.2943890 2.0340610 3.6094720
O -2.0432911 -0.0622970 1.3940520
27
 comment 
C 0.6785940 0.0895900 -1.2592160
C 0.0387820 -0.2150840 2.4559050
C 2.9046619 0.7487670 -0.4192210
C 1.9859340 0.2525420 -1.4530050
H 3.8832800 0.2704900 -0.3765630
H 2.3943379 -0.0007300 -2.4296930
H 0.0600560 -1.2667160 2.1762300
H 0.1859720 0.2598610 -0.3034400
O -0.1432220 -0.2500770 -2.3077281
C -1.0374310 -1.2852740 -2.1962149
O -1.8187211 -1.4521340 -3.0900691
C -0.9445940 -2.1436851 -0.9611460
H 0.0943740 -2.3994770 -0.7311130
H -1.5238889 -3.0499580 -1.1391890
H -1.3703721 -1.6133870 -0.1000140
C 1.0848000 0.3637940 3.0426750
H 1.9905159 -0.1934890 3.2636609
H 1.0843771 1.4159710 3.3185790
C 2.6278651 1.7370080 0.4325060
H 3.3405459 2.0497701 1.1910950
H 1.6883790 2.2834129 0.3780430
C -1.2120970 0.4977380 2.0776091
C -1.4083090 1.9328350 2.5109861
H -0.6641670 2.5774081 2.0282159
H -2.4065051 2.2563839 2.2129040
H -1.2890840 2.0420361 3.5936451
O -2.0483761 -0.0737650 1.3993220

{要扔掉的评论}

{包含4列的整数行数,CHAR FLOAT FLOAT FLOAT}

(每帧重复一次,但在行上使用不同的浮点数)

grammar XYZ;
/*
 * Parser Rules
 */

file                : header comment line+ EOF;
line                : ELEMENT FLOAT FLOAT FLOAT NEWLINE;
header              : INT NEWLINE;
comment             : WORD+ NEWLINE;
/*
 * Lexer Rules
*/

fragment LOWERCASE  : [a-z] ;
fragment UPPERCASE  : [A-Z] ;
fragment NUMBER     : [0-9]+ ;
INT                 : NUMBER ;
FLOAT               : '-'? NUMBER '.' NUMBER ;
WORD                : (LOWERCASE | UPPERCASE)+ ;
ELEMENT             : 'A' .. 'Z' ;
WHITESPACE          : (' '|'\t')+ -> skip ;
NEWLINE             : ('\r'? '\n' | '\r')+ ;
    AntlrInputStream istream = new AntlrInputStream(input);
    XYZLexer lexer = new XYZLexer(istream);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    XYZParser parser = new XYZParser(tokens);
    XYZParser.LineContext lineContext = parser.line();

    Console.WriteLine(lineContext.GetText());
    Console.ReadLine();

使用

    XYZParser.FileContext fileContext = parser.file();
    Console.WriteLine(fileContext.GetText());

相反,给我第3行:0不匹配的输入'C',需要元素

我如何才能从这个过程中摆脱错误并使用ANTLR运行时来获取数据?

grammar XYZ;
/*
 * Parser Rules
 */

file                : frame+ EOF;
frame               : header comment line+;
line                : ELEMENT FLOAT FLOAT FLOAT NEWLINE;
header              : INT NEWLINE;
comment             : (ELEMENT | WORD+) NEWLINE;
/*
 * Lexer Rules
*/

fragment LOWERCASE  : [a-z] ;
fragment UPPERCASE  : [A-Z] ;
fragment NUMBER     : [0-9]+ ;
INT                 : NUMBER ;
FLOAT               : '-'? NUMBER '.' NUMBER ;
ELEMENT             : 'A' .. 'Z' ;
WORD                : (LOWERCASE | UPPERCASE)+ ;
WHITESPACE          : (' '|'\t')+ -> skip ;
NEWLINE             : ('\r'? '\n' | '\r')+ ;
AntlrInputStream istream = new AntlrInputStream(input);
XYZLexer lexer = new XYZLexer(istream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
XYZParser parser = new XYZParser(tokens);
XYZParser.FileContext fileContext = parser.line();

Console.WriteLine(fileContext.GetText());
Console.ReadLine();
    AntlrInputStream istream = new AntlrInputStream(input);
    XYZLexer lexer = new XYZLexer(istream);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    XYZParser parser = new XYZParser(tokens);

    XYZParser.FileContext fileContext = parser.file();
    XYZParser.FrameContext frameContext = fileContext.frame()[0];
    XYZParser.LineContext lineContext = frameContext.line()[0];

    IParseTree tree = lineContext.FLOAT()[0];
    Console.WriteLine(tree.GetText());
    Console.ReadLine();

共有1个答案

张腾
2023-03-14
XYZParser.LineContext lineContext = parser.line();

您试图应用规则,该规则在开头需要一个元素,但输入以数字27开始,这是一个int,而不是元素。您应该改为应用规则文件,该规则在开头需要一个int

 类似资料:
  • 在 imi 框架中,使用注解可以实现很多功能。比如:路由、模型定义、事务、缓存等等 除了内置的注解以外,如果编写属于自己的注解呢? 这篇教程就来教大家来编写属于自己的注解。 注解定义 注解扫描 imi 是常驻内存运行的,所以冷启动时采用了全量扫描的方式,来实现注解缓存。使用的时候,就和读取配置一样简单高效。 一般需要在配置文件里的beanScan中,配置注解类所在命名空间。在 imi 框架中,涉及

  • 主要内容:创建项目(Project),添加源文件,编写代码并生成程序,编译(Complie),链接(Link),更加快捷的办法,总结本节,我们学习如何在新版 VS 2017 中编写程序输出“小牛知识库”,程序代码如下: 创建项目(Project) 在 VS 2017 下开发程序首先要创建项目,不同类型的程序对应不同类型的项目,初学者应该从控制台程序学起。   打开 VS 2017,在菜单栏中依次选择 “文件 --> 新建 --> 项目”:   或者直接按下 组合键,都会弹出下面的对话框:   选

  • 在ANTLR4中,我有一个lexer规则,说我可以使用任何字符得到任何单词,但空格和换行符除外。其定义如下: 我还有一个lexer规则(定义在than WORD之前),用于进入EVAL模式: 我考虑的另一个选择是将“word”定义为${and}包围的文本以外的任何东西。但我不知道如何创建这样的lexer规则。 我该怎么解决?要区分评价和词?

  • 下面是读取多个项目的自定义平面文件项目读取器的代码 } 下面是自定义项目编写器的代码 } 我是Spring批处理的新手。这段代码正确吗?我可能缺少任何用例?目前我的批处理作业按顺序执行,但将来可能会使用多线程和分区。 需要这样做是因为我需要在处理器中进行数据库查找。为多个项目进行查找比为单个项目进行查找要好。

  • 问题内容: 我有一个Java类,用户: 我收到一个包含来自Web服务的用户对象的JSON列表: 我试图编写一个自定义反序列化器: 但是我的解串器不起作用。如何为Gson编写自定义JSON解串器? 问题答案: 我假设User类具有适当的构造函数。

  • 本文向大家介绍详解JavaScript中的自定义事件编写,包括了详解JavaScript中的自定义事件编写的使用技巧和注意事项,需要的朋友参考一下 我们可以自定义事件来实现更灵活的开发,事件用好了可以是一件很强大的工具,基于事件的开发有很多优势(后面介绍)。 与自定义事件的函数有 Event、CustomEvent 和 dispatchEvent。 直接自定义事件,使用 Event 构造函数: C