Parsing 如何在Yacc(BISON)中打印解析器树
我使用BISON和FlEX为C语言制作了一个解析器。如果给定的c输入代码语法错误,它将在终端中工作并打印“语法错误”,否则将不打印任何内容 但是我想打印与给定c输入代码相关的解析器树,作为解析器的输出。我该怎么做?BISON中是否有可用于打印解析器树的函数?TXR语言(http://www.nongnu.org/txr)使用Flex和Yacc解析其输入。如果为解析树提供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的正则表
-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");
}
}
}