2014-04-30 20 views
1

我不確定標題是否清楚了我想要執行的操作。解析輸入並在解析時構建Dictionary/HashMap

我的解析器輸入包含有關C源文件的調試信息。一些輸入看起來像例如像這樣:

L:C$main.c$41$1$10:C0C5 

這基本上意味着在源文件main.c在該行10對應與所述存儲器地址C0C5

這裏有一個例子就是我AST的樣子:

enter image description here

表示輸入:

M:main 
L:C$main.c$29$1$0:C09C 
L:C$main.c$30$1$10:C0A2 
M:divide 
L:C$divice.c$31$1$10:C5A9 

我想要的是兩個散列的地圖,這樣我可以訪問這些信息在運行時很快。但是,我現在如何構建這樣的哈希映射,並且可以在parsetime處做到這一點?

這是我想用我的解析器:

public CDBFileParser getFileParser(String cdbFilePath) 
{ 
    Stream stream    = File.OpenRead(cdbFilePath); 
    ANTLRInputStream inputStream = new ANTLRInputStream(stream); 
    CDBFileLexer lexer   = new CDBFileLexer(inputStream); 
    CommonTokenStream tokens  = new CommonTokenStream(lexer); 
    CDBFileParser parser   = new CDBFileParser(tokens); 

    try 
    { 
     parser.TreeAdaptor = new CommonTreeAdaptor(); 
     parser.parseCDBFile(); 

     // All this works so far. Here comes the part I am looking for: 

     Modules[] modules = parser.getModules(); 
     Dictionary<int, int> lineToAddress = modules[0].getLineToAddressMap(); 
     Dictionary<int, int> addressToLine = modules[0].getAddressToLineMap(); 

     int address = 0xC09C; 

     System.Out.WriteLine("Address 0xC09C is at line " + addressToLine.get(address) + " in " + modules[0].getName()); 

    } 
    catch (Exception e) 
    { 
     printException(e); 
    } 

    return parser; 
} 

預期輸出:

Address 0xC09C is at line 29 in main 

有人能幫忙嗎?

此致敬禮。

回答

1

我正要刪除我的問題,但也許有人來到這篇文章。我剛剛過渡到ANTLR4,它確實更簡單(至少目前爲止)。

ANTLR4的接口(例如ICDBFileListener)是專爲你哪一個可以用它來捕獲所有信息在分析時

namespace Parser 
{ 
    public class CDBFileParserListener : ICDBFileListener 
    { 
     public void ExitModule_name(CDBFileParser.Module_nameContext context) 
     { 
      Console.WriteLine("ModuleName: " + context.GetText()); 
      // Add module to module-map and remember 
      // that current module is context.GetText() 
     } 

     public void ExitLine_number(CDBFileParser.Line_numberContext context) 
     { 
      Console.WriteLine("LineNumber: " + context.GetText()); 
      // Remember line number 
     } 

     public void ExitMemory_address(CDBFileParser.Memory_addressContext context) 
     { 
      Console.WriteLine("MemoryAddress: " + context.GetText()); 
      // Add linenumber <-> memoryaddress to maps 
     } 

     public Modules[] getModules() 
     { 
      return m_modules; 
     } 
    } 


} 

,這是它如何被使用:

public CDBFileParser getFileParser(String cdbFilePath) 
    { 
     Stream stream    = File.OpenRead(cdbFilePath); 
     AntlrInputStream inputStream = new AntlrInputStream(stream); 
     CDBFileLexer lexer   = new CDBFileLexer(inputStream);    
     CommonTokenStream tokens  = new CommonTokenStream(lexer); 
     CDBFileParser parser   = new CDBFileParser(tokens); 

     try 
     { 
      CDBFileParserListener listener = new CDBFileParserListener(); 
      parser.AddParseListener(listener); 
      System.Diagnostics.Debug.WriteLine(parser.parseCDBFile().ToStringTree()); 

      Dictionary<String, Module> modules = listener.Modules; 

      Module main; 
      modules.TryGetValue("main", out main); 

      long line = main.getLineFromAddress(0xC09C); 
      Console.WriteLine("0xC09C maps to " + line + " in main.c"); 
     } 
     catch (Exception e) 
     { 
      printException(e); 
     } 

     return parser; 
    }