help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Using %prec to resolve shift-reduce


From: Simon Richter
Subject: Using %prec to resolve shift-reduce
Date: Wed, 30 Nov 2016 19:54:56 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

Hi,

I have a grammar for ECMAScript, which has both brace delimited statement
blocks and brace delimited object literals, and allows expressions to be
used as statements, which creates conflicting interpretations for "{ }" as
either an empty block or an empty object.

The specification clarifies that expression statements may not begin,
among other things, with a brace, resolving the conflict. If I wanted to
transform that into rules, I'd have to create two versions of most of the
rules for expressions, one allowing object literals, one disallowing them.

So I'm wondering whether this could be resolved using %prec. My naive
implementation of a testcase would be

%token LBRACE "{"
%token RBRACE "}"

%token LPAREN "("
%token RPAREN ")"

%precedence LOWER
%precedence HIGHER

%%

statements:
        statements statement |
        %empty;

statement:
        block           %prec HIGHER |
        expression      %prec LOWER;

block:
        "{" statements "}";

expression:
        "(" expression ")" |
        object_literal;

object_literal:
        "{" "}";

My expectation would be that this compiles without conflicts, and creates
the following parse trees, enclosed in (statements( statements() ... ))

"{ }"           (block (statements()))
"( { } )"       (expression (expression( object_literal())))

However, this still creates a shift-reduce conflict, and parses

"{ }"           (expression( object_literal()))

Likewise, I'd like to resolve the dangling-else problem more locally:

%token IF "if"
%token ELSE "else"
%token SEMICOLON ";"

%precedence LOWER
%precedence HIGHER

%%

statement:
        if_statement |
        empty_statement;

if_statement:
        "if" /* expr omitted */ statement                       %prec LOWER |
        "if" /* expr omitted */ statement "else" statement      %prec HIGHER;

empty_statement:
        ";"

Here, I still get a shift-reduce conflict, but at least parsing does the
right thing due to the preference of shift over reduce.

I know I can solve dangling-else with

%precedence ")"         /* last terminal in alternative without "else" */
%precedence "else"      /* last terminal in alternative with "else" */

I have no idea though whether that will affect any other productions,
though, so I'd prefer a more local approach if possible.

Where am I going wrong here? Can I use %prec to achieve what I want?

   Simon



reply via email to

[Prev in Thread] Current Thread [Next in Thread]