我的日常工作包括合作开发一类Pascal编译器。我一直都沿着优化和代码生成。

我也想开始学习打造为同一种语言的简单语法分析器。不过我,真的不知道如何去了解这一点。 Flex和野牛似乎是选择。但是,是不是可以用C ++或C#写一个解析器?我有点爬行以C

的Yacc ++支持C#,但它是一个授权的一个。我在寻找的一切,我可以在这方面找到帮助。建议,将不胜感激。

有帮助吗?

解决方案

我相信你可以使用ANTLR用C#。我从来没有尝试过自己(还),但有一个教程的此处可能指向您在正确的方向。

其他提示

我个人推出自己词法分析器和解析器(LL)。这里是一个非常,缩写的例子。这是C ++,但希望你能适应它。它利用一个宏PARSE_HIGHER,使其容易插入在不同的优先级级别的运营商没有太多的代码改变。

 // routine to scan over whitespace/comments
void ScanWhite(const char* &pc){
  while(true){
    if(0);
    else if (WHITESPACE(*pc)) pc++;
    else if (pc[0]=='/' && pc[1]=='/'){
      while(*pc && *pc++ != '\n');
    }
    else break;
  }
}
// routine to lex an identifier
bool SeeId(const char* &pc, string sId){
  ScanWhite(pc);
  const char* pc0 = pc;
  if (alpha(*pc)){
    sId = "";
    while(alphanum(*pc)) sId += (*pc++);
    return true;
  }
  pc = pc0;
  return false;
}
// routine to lex a number
bool SeeNum(const char* &pc, double &dNum){
  ScanWhite(pc);
  const char* pc0 = pc;
  if (digit(*pc)){
    dNum = 0;
    while(digit(*pc)) dNum = dNum * 10 + (*pc++ - '0');
    if (*pc == '.'){
      double divisor = 1, frac = 0;
      while(digit(*pc)){
        divisor *= 0.1;
        frac += (*pc++ - '0') * divisor;
      }
      dNum += frac;
    }
    return true;
  }
  pc = pc0;
  return false;
}
// routine to lex some constant word
bool SeeWord(const char* &pc, const char* sWord){
  ScanWhite(pc);
  const char* pc0 = pc;
  int len = strlen(sWord);
  if (strncmp(pc, sWord, len)==0 && !alphanum(pc[len])){
    pc += len;
    return true;
  }
  pc = pc0;
  return false;
}
// routine to lex a single character like an operator
bool SeeChar(const char* &pc, const char c){
  ScanWhite(pc);
  const char* pc0 = pc;
  if (*pc == c){
    pc++;
    return true;
  }
  pc = pc0;
  return false;
}
// primitive expression parser
void ParsePrimitiveExpr(const char* &pc, CNode* &p){
  double dNum;
  char sId[100];
  if (0);
  else if (SeeNum(pc, dNum)){
    p = new CNode(dNum);
  }
  else if (SeeId(pc, sId)){
    // see if its a function call
    if (SeeChar(pc, '(')){
      p = MakeNewFunctionCallNode(sId);
      while(!SeeChar(pc, ')')){
        CNode* p1 = null;
        ParseExpression(pc, p1);
        AddArgumentExprToFunctionCallNode(p, p1);
        SeeChar(pc, ','); /* optional comma separator */
      }
    }
    // otherwise its just a variable reference
    else {
      p = new CNode(sId);
    }
  }
  // handle embedded expressions
  else if (SeeChar(pc, '(')){
    ParseExpression(pc, p);
    if (!SeeChar(pc, ')')) /* deal with syntax error */
  }
}
#define PARSE_HIGHER ParsePrimitiveExpr
// product parser
void ParseProduct(const char* &pc, CNode* &p){
  PARSE_HIGHER(pc, p);
  while(true){
    if (0);
    else if (SeeChar(pc, '*')){
      CNode p1 = null;
      PARSE_HIGHER(pc, p1);
      p = new CNode('*', p, p1);
    }
    else if (SeeChar(pc, '/')){
     CNode p1 = null;
     PARSE_HIGHER(pc, p1);
     p = new CNode('/', p, p1);
   }
   else break;
  }
}
#undef  PARSE_HIGHER
#define PARSE_HIGHER ParseProduct
// sum parser
void ParseSum(const char* &pc, CNode* &p){
  PARSE_HIGHER(pc, p);
  while(true){
    if (0);
    else if (SeeChar(pc, '+')){
      CNode p1 = null;
      PARSE_HIGHER(pc, p1);
      p = new CNode('+', p, p1);
    }
    else if (SeeChar(pc, '-')){
      CNode p1 = null;
      PARSE_HIGHER(pc, p1);
      p = new CNode('-', p, p1);
    }
   else break;
  }
}
#undef  PARSE_HIGHER
// can insert more routines like the above
// to handle move operators
#define PARSE_HIGHER ParseSum
// overall expression parser
void ParseExpression(const char* &pc, CNode* &p){
  PARSE_HIGHER(pc, p);
}

增加了一些帕斯卡式的语句的语法:

void ParseStatement(const char* &pc){
  char sId[100];
  if(0);
  else if (SeeWord(pc, "begin")){
    while(!SeeWord(pc, "end")){
      ParseStatement(pc);
      SeeChar(pc, ';');
    }
  }
  else if (SeeWord(pc, "while")){
    CNode* p1 = null;
    ParseExpression(pc, p1);
    ParseStatement(pc);
    /* semantics for while statement */
  }
  else if (SeeWord(pc, "if")){
    CNode* p1 = null;
    ParseExpression(pc, p1);
    ParseStatement(pc);
    if (SeeWord(pc, "else")){
      ParseStatement(pc);
    }
    /* semantics for if statement */
  }
  else if (SeeWord(pc, "for")){
    /* you do it */
  }
  // handle assignments and subroutine calls
  else if (SeeId(pc, sId)){
    if(0);
    else if (SeeChar(pc, '=')){
      CNode* p1 = null;
      ParseExpression(pc, p1);
      /* semantics for assignment statement */
    }
    else if (SeeChar(pc, '(')){
      CNode* p = MakeNewFunctionCallNode(sId);
      while(!SeeChar(pc, ')')){
        CNode* p1 = null;
        ParseExpression(pc, p1);
        AddArgumentExprToFunctionCallNode(p, p1);
        SeeChar(pc, ','); /* optional comma separator */
      }
    }
    else {
      /* we have a 1-word statement, which is OK in pascal */
    }
  }
  else {
    /* syntax error */
  }
}

它仍然需要语法数组索引,变量声明和函数定义,但我希望它是清楚如何做到这一点。

在他的经典编程文本,算法+数据结构=程序,尼克劳斯·维尔特开发一种简单Pascal0状语言整个递归下降语法分析器(以帕斯卡)。

如果你在使用Java编写它,我建议ANTLR。这是一个不错LL(*)分析器发电机用Java编写的。有一个了不起的书,它在亚马逊了。

野牛&挠曲是规范解析器生成器。如果你有兴趣在C ++中,我发现提振精神有用。我从来没有使用过它的任何东西一样复杂的编译器虽然。我相信其他人将有其他语言如C有趣的建议#...

您可以实际使用挠曲&野牛与C ++。在本教程,例如,你可以看到,第5节是致力于这一问题。只是谷歌它,我敢肯定,你会发现很多的例子。

我已经写有挠曲和野牛的XSLT解析器。更多最近我正在做使用ANTLR的一个项目,但:

是JFig语言语法(比Spring框架的XML DSL和更好的)有效和明确?

我喜欢在ANTLR工作程度远远超过了Flex和野牛。 ANTLR使您在抽象的,在某些方面上一个台阶。词法定义和语法分析器都可以去在一个文件中。 (ANTLR将生成令牌文件。)

其中一个关键项目是定义树语法的能力。基本上你在输入语言的语法解析和有复写高度优化AST树输出(这仍然为关联数据结构在内存中)的行动。然后,您可以将此树传递给在单独的树分析器文件中定义的另一个解析器。树分析器是你做你想做的行动项目的实际工作。

这是一个很好的方法,因为你可以保持AST的形式,并多次根据需要重新处理 - 剥离特定的子树节点基于后者的行动,打击处理等想想有点像语言解释器。代替从底层向上一遍一遍进入一个for循环和处理语言,可以只处理通过它的AST表示。

在我来说,我已经设计了一个bean工厂做的IoC依赖注入。我的bean工厂保持一个bean描述符的AST在周围运行。当需要作出(或检索)一个新的bean实例,我只是通过这个bean描述AST树到我的树分析器 - 结果是所需的bean实例(也有很多的因素去确定如何实例化请求的豆,包括制造被引用和/或经由元属性应用其他特殊行为)任何其他豆类。

最后,我目前的bean工厂的目标是Java的,但我想针对的ActionScript3和C#.NET。 ANTLR具有用于这样做支持。

如前所述,泰伦斯帕尔写了一本书关于如何使用ANTLR。这是针对工作需要做一些实事ANTLR的(而不是主题的学术处理)。

程序员

如果您想要C#按本问题尝试花园点GPPG和GPLEX。

当您使用Lex和Yacc你实际上并没有写任何东西在C 莱克斯是它自己的语言,是Yacc的。所以,你写在莱克斯词法分析器和的Yacc 。然而,对于帕斯卡,Lex和Yacc输入是已经可用

将所得的解析器和词法分析器具有I2C接口,这是真的。然而,大多数语言,包括C ++,简单的方法来调用(或包裹)C接口。

我不是这方面的专家,但我敢肯定,以上所有的无二ANTLR为好。

如果你问做,在“纯C ++”(知道是什么意思),考虑使用升压精神。我实在不明白在理论纯度点,如果它会导致一吨多的工作,虽然。

手工编写自己的词法分析器和解析器实际上是有点乐趣。词法分析器是的,你可以同时使用的转到和预处理证明极少数的情况之一。不过,我不会建议它像帕斯卡尔一个成熟的语言,如果你能避免它。这将是大量的工作。我说的是人 - 年。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top