gcc语法解析如何解决dangling else的问题?

文章讨论了GCC早期版本中ifelse嵌套的实现、PostgreSQLPLpgSQL中的ifelse语法规则,以及C语言中如何通过调整优先级解决shift/reduce冲突来处理elseif。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GCC上古版本(3.4)还有yacc,学习GCC如何实现if else 嵌套的问题。即:

问题

else后面的if到底是else if语义

if (xxx)
    a=1
else if (xxx) a=2

还是 else (语法块中的if else)。

if (xxx)
    a=1
else 
    if (xxx) a = 2 else a=2;

PostgreSQL的PLpgSQL中的if else

PostgreSQL中因为没有else if语法,只有elif,所以语法规则实现比较简单,没有dangling else的问题。

stmt_if			: K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
					{
						PLpgSQL_stmt_if *new;

						new = palloc0(sizeof(PLpgSQL_stmt_if));
						new->cmd_type	= PLPGSQL_STMT_IF;
						new->lineno		= plpgsql_location_to_lineno(@1);
						new->stmtid		= ++plpgsql_curr_compile->nstatements;
						new->cond		= $2;
						new->then_body	= $3;
						new->elsif_list = $4;
						new->else_body  = $5;

						$$ = (PLpgSQL_stmt *)new;
					}
				;

stmt_elsifs		:
					{
						$$ = NIL;
					}
				| stmt_elsifs K_ELSIF expr_until_then proc_sect
					{
						PLpgSQL_if_elsif *new;

						new = palloc0(sizeof(PLpgSQL_if_elsif));
						new->lineno = plpgsql_location_to_lineno(@2);
						new->cond   = $3;
						new->stmts  = $4;

						$$ = lappend($1, new);
					}
				;

stmt_else		:
					{
						$$ = NIL;
					}
				| K_ELSE proc_sect
					{
						$$ = $2;
					}
				;

GCC的解法

那么C语言中支持else if的语法:
c-parse


%token  IF ELSE

%nonassoc IF
%nonassoc ELSE

select_or_iter_stmt:
	  simple_if ELSE
		{ 
		    c_expand_start_else (); 
		    $<itype>1 = stmt_count; 
		}
	  c99_block_lineno_labeled_stmt
        { 
            c_finish_else ();
		    c_expand_end_cond ();
		    if (extra_warnings && stmt_count == $<itype>1)
		        warning ("empty body in an else-statement"); 
		 }
	| simple_if %prec IF
		{
		    c_expand_end_cond ();
		    if (extra_warnings && stmt_count++ == $<itype>1)
		        warning ("%Hempty body in an if-statement",&if_stmt_locus); 
		}
	| simple_if ELSE error
		{ c_expand_end_cond (); }

注意递归部分是simple_if:
在这里插入图片描述

  • c99_block_lineno_labeled_stmt代表语法块,可以包含if else。
  • 解决关键点:将simple_if非终结符的优先级降低到if,当出现else simple_if时,让simple_if去reduce。
  • 解决关键点:else的优先级比if要高,当else if出现时,发生shift/reduce冲突,根据优先级if会选择reduce。

《使用优先级解决shift/reduce冲突的经典例子(%prec UMINUS)》

在这里插入图片描述

手册中相关部分

https://www.gnu.org/software/bison/manual/bison.html#Shift_002fReduce

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高铭杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值