Использование antlr для анализа | отдельный файл - PullRequest
1 голос
/ 27 января 2010

Так что я думаю, что это должно быть легко, но мне тяжело с этим. Я пытаюсь разобрать | файл с разделителями и любая строка, которая не начинается с | это комментарий. Я думаю, я не понимаю, как работают комментарии. Это всегда ошибки в строке комментария. Это устаревший файл, поэтому его не нужно менять. Вот моя грамматика.

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

Данные:

! a comment
Another comment
| a | abc | b | def | ...

Ответы [ 3 ]

1 голос
/ 27 января 2010

Грамматика для этого будет выглядеть так:

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;} 
  ;

Теперь сгенерируйте лексер / парсер, вызвав:

java -cp antlr-3.2.jar org.antlr.Tool Route.g

создать класс 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);
    }
  }
}

Скомпилируйте все исходные файлы:

javac -cp antlr-3.2.jar *.java

и запустить класс 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]

Редактировать: обратите внимание, что я немного упростил это, разрешив только строчные буквы, вы всегда можете расширить набор.

0 голосов
/ 27 января 2010

Это похоже на работу, клянусь, я попробовал. Изменение комментария на строчные буквы переключило его на анализатор против лексера, я все еще не понимаю

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
0 голосов
/ 27 января 2010

Хорошая идея использовать ANTLR для такой работы, хотя я думаю, что это излишне. Например, было бы очень легко (в псевдокоде):

for each line in file:
if line begins with '|':
    fields = /|\s*([a-z]+)\s*/g

Изменить: Ну, вы не можете выразить различие между комментариями и строками лексически , потому что нет ничего лексического, что отличает их. Подсказка, которая поможет вам в одном направлении.

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