2013-03-24 122 views
0

我已經給出了項目,使語法分析器使用任何編程語言。我正在用C#做。簡單的上下文無關語法已經創建。但是現在我非常困惑地爲語法分析器製作算法。語法分析器在c#

語法是這樣的:

Namespace  var . { class } 
    Class   var . { method } . class | null 
    Method   function | null 
    Function  return_type.var.(function_arguements).{.stmt_list.} . Method 
        .......... and so on 

我必須表明的錯誤,行號的錯誤也是如此。我需要一些指導,甚至開始編碼。我試過二維數組,鏈表,枚舉,結構。但我無法爲此創建任何好的算法。

+1

我建議你找一本好的編譯器設計教科書並閱讀它。關於這件事還有一些不錯的文章:http://www.pling.org.uk/cs/lsa.html&http://www.cs.huji.ac.il/course/2002/nand2tet/ docs/ch_10_compiler_I.pdf但是你需要做的是定義一個語法,獲得代碼標記,並開始分析令牌和它們進來的順序。 – Cheesebaron 2013-03-24 14:13:12

回答

2

當我使用編譯器時,我們必須編寫一個簡單語言的編譯器。我不知道我是否完全按照您的問題中的語言定義進行了操作,或者您已經掌握了多少程度,但這是我們在解析語言時使用的方法。

首先,您需要一個詞法分析器類,它只負責獲取輸入中的下一個標記。這基本上是通過代碼進行的,每次調用GetNextToken()都會返回代碼中的下一個字符串。所以說你有下面的代碼行:

PROCEDURE sum() RETURN INTEGER; 

GetNextToken()的第一次調用將返回PROCEDURE。第二次調用將返回sum,第三個將返回(然後)然後RETURNINTEGER,最後;

現在你需要一個句法分析器。這個想法是,你的語言定義最終應該終止令牌。這裏是我的編譯語言定義的小SNIPPIT:

<program> -> $UNIT <prog-identifier> $SEMICOLON 
        <block> $PERIOD 
<block> -> [<label-declaration>] 
        {<variable-dec-sec>}* 
        {<procedure-declaration>}* 
        $LEFTBRACE <statement> {$SEMICOLON <statement>}* 
        $RIGHTBRACE 

所以在分析我們調用一個函數Program()Program()會得到下一個令牌。如果該令牌是UNIT,我們會得到另一個函數ProgIdentifier(),它將再次調用GetNextToken()ProgramIdentifier()會查找標識符類型。看看Program(),看下一個標記是否爲;。然後撥打Block(),其工作方式與Program()相同,然後查看您之後是否有.

關鍵是,在每個結束標記處,例如,;,您將擁有if語句。因此,對於Program()簡單的代碼可能是這樣的:

public int Program() 
{ 
    lex.GetNextToken(); 
     if (lex.InternalCode == TokenTable.UNIT) 
     { 
      lex.GetNextToken(); 
      ProgIdentifier(); 
      if (lex.InternalCode == TokenTable.SEMICOLON) 
      { 
       lex.GetNextToken(); 
       Block(); 
       if (parseErrors) 
       { 
        //Drop out into Statement Level Parsing 
        //Statement Level Parsing just calls Statement() for <statement> 
        //until you have gone through the entire input. 
        //The point is to avoid getting many errors if you are missing a 
        //single token. 
        StatementLevelParse(); 
       } 
       if (lex.InternalCode == TokenTable.PERIOD) 
       { 
        lex.GetNextToken(); 
        if (lex.EndOfFile) 
        { 
         if (!parseFailed) 
         { 
          //Success 
          echo("Success"); 
         } 
         else 
         { 
          echo("Parse Failed"); 
         } 
        } 
        else 
        { 
         Error(lex.CurrentLine, 200, false, "Expected End Of File: Found " + lex.NextSymbol); 
        } 
       } 
       else 
       { 
        //Fail. Expected $PERIOD 
        Error(lex.CurrentLine, 200, false, "Expected \".\": Found " + lex.NextSymbol); 
       } 
      } 
      else 
      { 
       //Fail. Expected $SEMICOLON 
       Error(lex.CurrentLine, 200, false, "Expected \";\": Found " + lex.NextSymbol); 
      } 
     } 
     else 
     { 
      //Fail. Expected $UNIT 
      Error(lex.CurrentLine, 200, false, "Expected \"UNIT\": Found " + lex.NextSymbol); 
     } 
     EchoOutput("LEAVING PROGRAM"); 
     return 0; 
} 

我現在看到,這是一個很大閱讀。我不確定這是否是您的導師希望您採取或不需要的方法,但是如果您瞭解您的語言,我發現它非常簡單易用。我不保證這是做這件事最有效或最有效的方法,只是我需要使用的方法。

我真的很希望我能正確理解你的問題...