Parsing 如何在Yacc(BISON)中打印解析器树

Parsing 如何在Yacc(BISON)中打印解析器树,parsing,bison,yacc,Parsing,Bison,Yacc,我使用BISON和FlEX为C语言制作了一个解析器。如果给定的c输入代码语法错误,它将在终端中工作并打印“语法错误”,否则将不打印任何内容 但是我想打印与给定c输入代码相关的解析器树,作为解析器的输出。我该怎么做?BISON中是否有可用于打印解析器树的函数?TXR语言(http://www.nongnu.org/txr)使用Flex和Yacc解析其输入。如果为解析树提供-v选项,则可以看到它 例如: 如您所见,构建AST在很大程度上只是简单地构建嵌套列表。 这张表格很方便编译。基于NFA的正则表

我使用BISON和FlEX为C语言制作了一个解析器。如果给定的c输入代码语法错误,它将在终端中工作并打印“语法错误”,否则将不打印任何内容

但是我想打印与给定c输入代码相关的解析器树,作为解析器的输出。我该怎么做?BISON中是否有可用于打印解析器树的函数?

TXR语言(http://www.nongnu.org/txr)使用Flex和Yacc解析其输入。如果为解析树提供
-v
选项,则可以看到它

例如:

如您所见,构建AST在很大程度上只是简单地构建嵌套列表。 这张表格很方便编译。基于NFA的正则表达式编译器的顶级函数可读性很强:

/*
 * Input is the items from a regex form,
 * not including the regex symbol.
 * I.e.  (rest '(regex ...)) not '(regex ...).
 */
static nfa_t nfa_compile_regex(val exp)
{
  if (nullp(exp)) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_empty(acc, 0);
    return nfa_make(s, acc);
  } else if (typeof(exp) == chr_s) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_single(acc, c_chr(exp));
    return nfa_make(s, acc);
  } else if (exp == wild_s) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_wild(acc);
    return nfa_make(s, acc);
  } else {
    val sym = first(exp), args = rest(exp);

    if (sym == set_s) {
      return nfa_compile_set(args, nil);
    } else if (sym == cset_s) {
      return nfa_compile_set(args, t);
    } else if (sym == compound_s) {
      return nfa_compile_list(args);
    } else if (sym == zeroplus_s) {
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *acc = nfa_state_accept();
      /* New start state has empty transitions going through
         the inner NFA, or skipping it right to the new acceptance state. */
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, acc);
      /* Convert acceptance state of inner NFA to one which has
         an empty transition back to the start state, and
         an empty transition to the new acceptance state. */
      nfa_state_empty_convert(nfa_arg.accept, nfa_arg.start, acc);
      return nfa_make(s, acc);
    } else if (sym == oneplus_s) {
      /* One-plus case differs from zero-plus in that the new start state
         does not have an empty transition to the acceptance state.
         So the inner NFA must be traversed once. */
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *acc = nfa_state_accept();
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, 0); /* <-- diff */
      nfa_state_empty_convert(nfa_arg.accept, nfa_arg.start, acc);
      return nfa_make(s, acc);
    } else if (sym == optional_s) {
      /* In this case, we can keep the acceptance state of the inner
         NFA as the acceptance state of the new NFA. We simply add
         a new start state which can short-circuit to it via an empty
         transition.  */
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, nfa_arg.accept);
      return nfa_make(s, nfa_arg.accept);
    } else if (sym == or_s) {
      /* Simple: make a new start and acceptance state, which form
         the ends of a spindle that goes through two branches. */
      nfa_t nfa_first = nfa_compile_regex(first(args));
      nfa_t nfa_second = nfa_compile_regex(second(args));
      nfa_state_t *acc = nfa_state_accept();
      /* New state s has empty transitions into each inner NFA. */
      nfa_state_t *s = nfa_state_empty(nfa_first.start, nfa_second.start);
      /* Acceptance state of each inner NFA converted to empty
         transition to new combined acceptance state. */
      nfa_state_empty_convert(nfa_first.accept, acc, 0);
      nfa_state_empty_convert(nfa_second.accept, acc, 0);
      return nfa_make(s, acc);
    } else {
      internal_error("bad operator in regex");
    }
  }
}
/*
*输入是来自正则表达式表单的项,
*不包括正则表达式符号。
*即(rest'(regex…)而不是(regex…)。
*/
静态nfa\u t nfa\u编译\u正则表达式(val exp)
{
if(nullp(exp)){
nfa_state_t*acc=nfa_state_accept();
nfa_state_t*s=nfa_state_empty(acc,0);
返回nfa_品牌(s、acc);
}else if(类型(exp)=chr_s){
nfa_state_t*acc=nfa_state_accept();
nfa_state_t*s=nfa_state_single(acc,c_chr(exp));
返回nfa_品牌(s、acc);
}else if(exp==wild_s){
nfa_state_t*acc=nfa_state_accept();
nfa_state_t*s=nfa_state_wild(acc);
返回nfa_品牌(s、acc);
}否则{
val sym=first(exp),args=rest(exp);
如果(sym==set_s){
返回nfa\u编译集(args,nil);
}else if(sym==cset_s){
返回nfa\u编译集(args,t);
}else if(sym==化合物){
返回nfa\u编译\u列表(args);
}else if(sym==zeroplus){
nfa_t nfa_arg=nfa_compile_regex(first(args));
nfa_state_t*acc=nfa_state_accept();
/*新的开始状态有空的转换
内部NFA,或将其直接跳过到新的接受状态*/
nfa_state_t*s=nfa_state_empty(nfa_arg.start,acc);
/*将内部NFA的接受状态转换为
返回开始状态的空转换,以及
到新接受状态的空转换*/
nfa_state_empty_convert(nfa_arg.accept、nfa_arg.start、acc);
返回nfa_品牌(s、acc);
}else if(sym==oneplus){
/*一个加号的情况与零加号的不同之处在于,新的启动状态
没有到接受状态的空转换。
因此,内部NFA必须遍历一次*/
nfa_t nfa_arg=nfa_compile_regex(first(args));
nfa_state_t*acc=nfa_state_accept();

nfa_state_t*s=nfa_state_empty(nfa_arg.start,0);/*您的意思是要为您解析的表达式打印AST吗?如果是这样,您需要自己实现--我可以合理地确定yacc和Bison都没有为您做任何事情。
regexpr : regbranch                     { $$ = if3(cdr($1), 
                                                   cons(compound_s, $1),
                                                   car($1)); }
        | regexpr '|' regexpr           { $$ = list(or_s, $1, $3, nao); }
        | regexpr '&' regexpr           { $$ = list(and_s, $1, $3, nao); }
        | '~' regexpr                   { $$ = list(compl_s, $2, nao); }
        | /* empty */ %prec LOW         { $$ = nil; }
        ;
/*
 * Input is the items from a regex form,
 * not including the regex symbol.
 * I.e.  (rest '(regex ...)) not '(regex ...).
 */
static nfa_t nfa_compile_regex(val exp)
{
  if (nullp(exp)) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_empty(acc, 0);
    return nfa_make(s, acc);
  } else if (typeof(exp) == chr_s) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_single(acc, c_chr(exp));
    return nfa_make(s, acc);
  } else if (exp == wild_s) {
    nfa_state_t *acc = nfa_state_accept();
    nfa_state_t *s = nfa_state_wild(acc);
    return nfa_make(s, acc);
  } else {
    val sym = first(exp), args = rest(exp);

    if (sym == set_s) {
      return nfa_compile_set(args, nil);
    } else if (sym == cset_s) {
      return nfa_compile_set(args, t);
    } else if (sym == compound_s) {
      return nfa_compile_list(args);
    } else if (sym == zeroplus_s) {
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *acc = nfa_state_accept();
      /* New start state has empty transitions going through
         the inner NFA, or skipping it right to the new acceptance state. */
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, acc);
      /* Convert acceptance state of inner NFA to one which has
         an empty transition back to the start state, and
         an empty transition to the new acceptance state. */
      nfa_state_empty_convert(nfa_arg.accept, nfa_arg.start, acc);
      return nfa_make(s, acc);
    } else if (sym == oneplus_s) {
      /* One-plus case differs from zero-plus in that the new start state
         does not have an empty transition to the acceptance state.
         So the inner NFA must be traversed once. */
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *acc = nfa_state_accept();
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, 0); /* <-- diff */
      nfa_state_empty_convert(nfa_arg.accept, nfa_arg.start, acc);
      return nfa_make(s, acc);
    } else if (sym == optional_s) {
      /* In this case, we can keep the acceptance state of the inner
         NFA as the acceptance state of the new NFA. We simply add
         a new start state which can short-circuit to it via an empty
         transition.  */
      nfa_t nfa_arg = nfa_compile_regex(first(args));
      nfa_state_t *s = nfa_state_empty(nfa_arg.start, nfa_arg.accept);
      return nfa_make(s, nfa_arg.accept);
    } else if (sym == or_s) {
      /* Simple: make a new start and acceptance state, which form
         the ends of a spindle that goes through two branches. */
      nfa_t nfa_first = nfa_compile_regex(first(args));
      nfa_t nfa_second = nfa_compile_regex(second(args));
      nfa_state_t *acc = nfa_state_accept();
      /* New state s has empty transitions into each inner NFA. */
      nfa_state_t *s = nfa_state_empty(nfa_first.start, nfa_second.start);
      /* Acceptance state of each inner NFA converted to empty
         transition to new combined acceptance state. */
      nfa_state_empty_convert(nfa_first.accept, acc, 0);
      nfa_state_empty_convert(nfa_second.accept, acc, 0);
      return nfa_make(s, acc);
    } else {
      internal_error("bad operator in regex");
    }
  }
}