前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >gcc语法解析如何解决dangling else的问题?

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

作者头像
mingjie
发布2023-10-13 10:30:57
2170
发布2023-10-13 10:30:57
举报
文章被收录于专栏:Postgresql源码分析

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

问题

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

代码语言:javascript
复制
if (xxx)
    a=1
else if (xxx) a=2

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

代码语言:javascript
复制
if (xxx)
    a=1
else 
    if (xxx) a = 2 else a=2;

PostgreSQL的PLpgSQL中的if else

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

代码语言:javascript
复制
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

代码语言:javascript
复制
%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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • PostgreSQL的PLpgSQL中的if else
  • GCC的解法
  • 手册中相关部分
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档