2010-01-26 38 views
1

所以我認爲這應該很容易,但我有一個艱難的時間。我試圖解析一個|分隔文件以及任何不以|開頭的行是一條評論。我想我不明白評論如何工作。它總是在註釋行上出錯。這是一個傳統文件,所以沒有改變它。這是我的語法。使用antlr解析|分開的文件

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 | ... 
+0

歡迎來到SO!小提示:您應該用4個空格縮進代碼,這會導致該站點解析並顯示爲代碼,這可以通過突出顯示塊並按頂部的「代碼」按鈕或點擊Ctrl + K來完成。 – RCIX 2010-01-26 22:49:35

+0

謝謝,這是我第一次發佈Stack Overflow,感謝熱烈的歡迎。 – Ben 2010-01-26 23:06:19

回答

0

這是一個不錯的主意,使用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)+; 
+0

好吧,我同意,但我試圖選擇一個容易的事情與antlr做開始。 – Ben 2010-01-26 23:04:48

0

這似乎工作,我發誓我試過了。將註釋更改爲小寫將其轉換爲解析器與詞法分析器,但我仍然不明白。

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

看到我的答案。 * lexing *(將文本轉換爲令牌)和* parsing *(理解令牌)之間的區別。 – 2010-01-27 01:58:25

1

,一種在語法應該是這樣的:

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] 

編輯:請注意,我通過只允許小寫字母來簡化它,您可以隨時擴展套餐。