2013-03-24 125 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; 
} 

我现在看到,这是一个很大阅读。我不确定这是否是您的导师希望您采取或不需要的方法,但是如果您了解您的语言,我发现它非常简单易用。我不保证这是做这件事最有效或最有效的方法,只是我需要使用的方法。

我真的很希望我能正确理解你的问题...