2017-04-02 76 views
1

我在ANTLR中創建了以下用於解析csv文件的語法。在c#中使用ANTLR解析csv

grammar CSV; 

file returns [List<List<string>> data] 
@init {$data = new List<List<string>>();} 
: (row {$data.Add($row.list);})+ EOF 
; 

row returns [List<string> list] 
@init {$list = new List<string>();} 
: a=value { 
     $list.Add($a.val); 
    } 
    (Comma b=value { 
     $list.Add($b.val);} 
     )* 
     (LineBreak | EOF) 
; 

value returns [string val] 
: SimpleValue {$val = $SimpleValue.text;} 
| QuotedValue 
    { 
    System.Console.WriteLine($val); 
    $val = $QuotedValue.text; 
    $val = $val.Substring(1, $val.Length-1); 
    $val = $val.Replace("\"\"", "\""); 
    } 
; 

Comma : 
(' '* ',' ' '*); 

LineBreak : 
'\r'? '\n'; 

SimpleValue 
: ~[,\r\n"]+ 
; 

QuotedValue 
: '"' ('""' | ~'"')* '"' 
; 

上面的語法是解析下面的csv文件沒有錯誤。

a,b 
1,2 
3,4 

,但是當我解析以下csv文件它拋出以下錯誤

a,b 
,2 
3,4 

line 2:0 extraneous input ',' expecting {<EOF>, SimpleValue, QuotedValue} 

可以有人指導我如何解決這個問題?

主程序

public List<List<string>> Parse() 
     { 
      string csvData = string.Empty; 
      if (string.IsNullOrEmpty(_path)) 
       throw new ArgumentException("Path can not be empty"); 

      try 
      { 

       csvData = File.ReadAllText(_path); 

      } 
      catch (Exception) 
      { 

       throw new FileNotFoundException(string.Format("{0} not found", _path)); 
      } 

      // create an instance of the lexer 
      CSVLexer lexer = new CSVLexer(new AntlrInputStream(csvData)); 

      // wrap a token-stream around the lexer 
      CommonTokenStream tokens = new CommonTokenStream(lexer); 

      // create the parser 
      CSVParser parser = new CSVParser(tokens); 

      // invoke the entry point of our grammar 
      _results = parser.file().data; 


      return _results; 
     } 

UPADTE

按照麥克蚶答案我有如下更新的行規。現在,我沒有得到任何錯誤

row returns [List<string> list] 
@init {$list = new List<string>();} 
: Comma? a=value { 
     $list.Add($a.val); 

    } 
    (Comma b=value { 
     $list.Add($b.val); 
     } 
     )* 
     (LineBreak | EOF) 
; 

回答

1

顯然你row規則是不夠靈活,無法處理缺失值。你應該使用這樣的事情,而不是:

row: Comma? value (Comma value)*; 

增加了對領先的逗號(實際上是缺少第一個值)的可能性。

建議:不要在語法中使用動作代碼來收集值。而是創建一個解析監聽器並將其分配給您的解析器,解析器在解析過程中觸發其方法,以執行所有後臺工作。它使語法更加清潔,並允許使用它與實際目標語言無關。

+0

如何在我的語法中添加行規 – muski

+0

對不起,我不明白你的問題。如何將任何文本添加到您的語法? –

+0

我已更新我的問題。在您提出修改後,現在我沒有收到任何錯誤 – muski