使用antlr解析|分隔的文件

使用antlr解析|分隔的文件,antlr,Antlr,所以我认为这应该很容易,但我现在很难接受。我试图解析一个|分隔的文件,任何不以|开头的行都是注释。我想我不明白评论是怎么起作用的。它总是在注释行中出错。这是一个遗留文件,因此无法更改它。这是我的语法 grammar Route; @header { package org.benheath.codegeneration; } @lexer::header { package org.benheath.codegeneration; } file: line+; line: route+ '

所以我认为这应该很容易,但我现在很难接受。我试图解析一个|分隔的文件,任何不以|开头的行都是注释。我想我不明白评论是怎么起作用的。它总是在注释行中出错。这是一个遗留文件,因此无法更改它。这是我的语法

grammar Route;

@header {
package org.benheath.codegeneration;
}

@lexer::header {
package org.benheath.codegeneration;
}

file: line+;
line: route+ '\n';
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ;
elt: (ELEMENT)*;

COMMENT: ~'|' .* '\n' ;
ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ;
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace
数据:


在这样的工作中使用ANTLR是一个好主意,尽管我确实认为这有点过头了。例如,很容易(在伪代码中):

编辑:你不能用词汇来表达注释和行之间的区别,因为没有词汇来区分它们。一个让你朝着一个可行方向前进的提示

line: comment | fields;
comment: NONBAR+ (BAR|NONBAR+) '\n';
fields = (BAR NONBAR)+;

在这样的工作中使用ANTLR是一个好主意,尽管我确实认为这有点过头了。例如,很容易(在伪代码中):

编辑:你不能用词汇来表达注释和行之间的区别,因为没有词汇来区分它们。一个让你朝着一个可行方向前进的提示

line: comment | fields;
comment: NONBAR+ (BAR|NONBAR+) '\n';
fields = (BAR NONBAR)+;

这似乎管用,我发誓我试过了。将注释改为小写将其切换到解析器vs lexer,我仍然不明白

grammar Route;

@header {
    package org.benheath.codegeneration;
}

@lexer::header {
    package org.benheath.codegeneration;
}

file: (line|comment)+;
line: route+ '\n';
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ;
elt: (ELEMENT)*;

comment : ~'|' .* '\n';

ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ;
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace

这似乎管用,我发誓我试过了。将注释改为小写将其切换到解析器vs lexer,我仍然不明白

grammar Route;

@header {
    package org.benheath.codegeneration;
}

@lexer::header {
    package org.benheath.codegeneration;
}

file: (line|comment)+;
line: route+ '\n';
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ;
elt: (ELEMENT)*;

comment : ~'|' .* '\n';

ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ;
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace

其语法如下所示:

parse
  :  line* EOF   
  ;

line
  :  ( comment | values ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values
  :  PIPE ( ELEMENT PIPE )+
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
grammar Route;

@members {
  List<List<String>> values = new ArrayList<List<String>>();
}

parse
  :  line* EOF   
  ;

line
  :  ( comment | v=values {values.add($v.line);} ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values returns [List<String> line]
@init {line = new ArrayList<String>();}
  :  PIPE ( e=ELEMENT {line.add($e.text);} PIPE )*
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
为了测试它,您只需要在语法中添加一些代码,如下所示:

parse
  :  line* EOF   
  ;

line
  :  ( comment | values ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values
  :  PIPE ( ELEMENT PIPE )+
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
grammar Route;

@members {
  List<List<String>> values = new ArrayList<List<String>>();
}

parse
  :  line* EOF   
  ;

line
  :  ( comment | v=values {values.add($v.line);} ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values returns [List<String> line]
@init {line = new ArrayList<String>();}
  :  PIPE ( e=ELEMENT {line.add($e.text);} PIPE )*
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
创建一个类
RouteTest.java

import org.antlr.runtime.*;
import java.util.List;

public class RouteTest {
  public static void main(String[] args) throws Exception {
    String data = 
        "a comment\n"+
        "| xxxxx | y |     zzz   |\n"+
        "another comment\n"+
        "| a | abc | b | def |";
    ANTLRStringStream in = new ANTLRStringStream(data);
    RouteLexer lexer = new RouteLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    RouteParser parser = new RouteParser(tokens);
    parser.parse();
    for(List<String> line : parser.values) {
      System.out.println(line);
    }
  }
}
并运行类
RouteTest

// Windows
java -cp .;antlr-3.2.jar RouteTest

// *nix/MacOS
java -cp .:antlr-3.2.jar RouteTest
如果一切顺利,您可以在控制台上看到以下内容:

[xxxxx, y, zzz]
[a, abc, b, def]

编辑:请注意,我只允许小写字母,因此简化了一点。当然,您可以随时扩展该集合。

该集合的语法如下所示:

parse
  :  line* EOF   
  ;

line
  :  ( comment | values ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values
  :  PIPE ( ELEMENT PIPE )+
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
grammar Route;

@members {
  List<List<String>> values = new ArrayList<List<String>>();
}

parse
  :  line* EOF   
  ;

line
  :  ( comment | v=values {values.add($v.line);} ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values returns [List<String> line]
@init {line = new ArrayList<String>();}
  :  PIPE ( e=ELEMENT {line.add($e.text);} PIPE )*
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
为了测试它,您只需要在语法中添加一些代码,如下所示:

parse
  :  line* EOF   
  ;

line
  :  ( comment | values ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values
  :  PIPE ( ELEMENT PIPE )+
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
grammar Route;

@members {
  List<List<String>> values = new ArrayList<List<String>>();
}

parse
  :  line* EOF   
  ;

line
  :  ( comment | v=values {values.add($v.line);} ) ( NL | EOF )
  ;

comment
  :  ELEMENT+
  ;

values returns [List<String> line]
@init {line = new ArrayList<String>();}
  :  PIPE ( e=ELEMENT {line.add($e.text);} PIPE )*
  ;

PIPE
  :  '|'    
  ;

ELEMENT
  :  ('a'..'z')+
  ;

NL
  :  '\r'? '\n' |  '\r' 
  ;

WS
  :  (' '|'\t') {$channel=HIDDEN;} 
  ;
创建一个类
RouteTest.java

import org.antlr.runtime.*;
import java.util.List;

public class RouteTest {
  public static void main(String[] args) throws Exception {
    String data = 
        "a comment\n"+
        "| xxxxx | y |     zzz   |\n"+
        "another comment\n"+
        "| a | abc | b | def |";
    ANTLRStringStream in = new ANTLRStringStream(data);
    RouteLexer lexer = new RouteLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    RouteParser parser = new RouteParser(tokens);
    parser.parse();
    for(List<String> line : parser.values) {
      System.out.println(line);
    }
  }
}
并运行类
RouteTest

// Windows
java -cp .;antlr-3.2.jar RouteTest

// *nix/MacOS
java -cp .:antlr-3.2.jar RouteTest
如果一切顺利,您可以在控制台上看到以下内容:

[xxxxx, y, zzz]
[a, abc, b, def]

编辑:请注意,我只允许小写字母,因此简化了一点。当然,您可以随时扩展集合。

欢迎使用SO!小提示:您应该将代码缩进4个空格,这将导致此站点解析并显示为代码,这可以通过突出显示块并按下顶部的“代码”按钮或按Ctrl+K来完成。谢谢,这是我第一篇关于堆栈溢出的帖子,感谢大家的热烈欢迎。欢迎来到SO!小提示:您应该将代码缩进4个空格,这将导致此站点解析并显示为代码,这可以通过突出显示块并按下顶部的“代码”按钮或按Ctrl+K来完成。谢谢,这是我第一次发布堆栈溢出,感谢您的热情欢迎。我同意,但是我试着选择一件简单的事情来开始使用antlr。我同意,但我试着选择一件简单的事情来开始使用antlr。见我的答案。这是词法分析(将文本转换为标记)和解析(理解标记)之间的区别。参见我的答案。这是词法分析(将文本转换为标记)和解析(理解标记)之间的区别。