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

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

注意递归部分是simple_if:
gcc语法解析如何解决dangling else的问题?_第1张图片

  • 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)》

gcc语法解析如何解决dangling else的问题?_第2张图片

手册中相关部分

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

gcc语法解析如何解决dangling else的问题?_第3张图片

你可能感兴趣的:(pgsql,general,lang,gcc,postgresql,else,dangling)