0

I'm making a parser for a language similar to C. I have problem to the statement expression .

I've seen at many posts how they have the declaration of the expression, but for me it doesn't work... I have many conflicts. Can you help me please?

.y file :

%{ 
    #include <stdio.h> 
    #include <stdlib.h>
    extern FILE *yyin; 
    extern int yylex(); 
    int line=1; 
    int error=0; 
    #define YYERROR_VERBOSE 

    void yyerror(const char *msg) 
    { 
        error = 1; 
        printf("ERROR in line %d : %s.\n", line, msg); 
    } 
%}

%expect 2
%start programme
%token SEMICOLON
%token COMMA
%token L_PARENTHESIS
%token R_PARENTHESIS
%token L_REC_BRACKET
%token R_REC_BRACKET
%token L_CURLY_BRACKET
%token R_CURLY_BRACKET
%token QUESTION_MARK
%token COLON
%token DOT
%token AND
%token STAR
%token PLUS
%token MINUS
%token EXCLAMATION_MARK
%token SLASH
%token PERCENT
%token LESS
%token GREATER
%token LESS_EQUAL
%token GREATER_EQUAL
%token EQUAL
%token NOT_EQUAL
%token LOGIC_AND
%token LOGIC_OR
%token UN_PLUS
%token UN_MINUS
%token EQ
%token MUL_EQUAL
%token DIV_EQUAL
%token MOD_EQUAL
%token PLUS_EQUAL
%token MINUS_EQUAL
%token TRUE
%token FALSE
%token NUL
%token NUMBER
%token T_WORD
%token WORD


    %right L_PARENTHESIS SEMICOLON
%nonassoc STAR 
%right SLASH PERCENT PLUS MINUS LESS GREATER 
%right LESS_EQUAL GREATER_EQUAL EQUAL NOT_EQUAL LOGIC_AND LOGIC_OR          
%right UN_PLUS UN_MINUS              
%right AND EXCLAMATION_MARK        
%right EQ MUL_EQUAL DIV_EQUAL MOD_EQUAL PLUS_EQUAL MINUS_EQUAL

%%

programme : expression;
expression : TRUE 
           | FALSE 
           | NUL               
           | id L_PARENTHESIS list_exp R_PARENTHESIS 
           | expression L_REC_BRACKET expression R_REC_BRACKET
           | unitary_op expression
           | expression binary_op exp
           | unitary_op_assig expression
           | expression unitary_op_assig
           | expression binary_op_assig expression  
           | expression QUESTION_MARK expression COLON expression
           | exp
           | DELETE expression
;
exp : T_WORD 
    | id
    | L_PARENTHESIS expression R_PARENTHESIS
    | double_const;
id: WORD;
list_exp : list expression; 

list: | list_exp COMMA;

int_const : NUMBER int_const
          | NUMBER;

double_const : int_const 
             | int_const DOT int_const;

binary_op : STAR
          | SLASH
          | PERCENT
          | PLUS
          | MINUS
          | LESS
          | GREATER
          | LESS_EQUAL
          | GREATER_EQUAL
          | EQUAL
          | NOT_EQUAL
          | LOGIC_AND
          | LOGIC_OR;

unitary_op_assig : UN_PLUS
                 | UN_MINUS;

unitary_op : AND
           | STAR
           | PLUS
           | MINUS
           | EXCLAMATION_MARK;

binary_op_assig : EQ
                | MUL_EQUAL
                | DIV_EQUAL
                | MOD_EQUAL
                | PLUS_EQUAL
                | MINUS_EQUAL;

%%

int main(int argc, char *argv[])
{       
    if(argc == 2) yyin = fopen(argv[1], "r");
    else if(argc < 2){
        printf("No file found.\n");
        return 0;
    } else{
         printf("Only one file is permitted.\n");
        return 0;
    }

    yyparse ();
    if(error == 0) printf("Finished at %d line. No errors!\n",line); 
    return 0; 
}

.l file

%{
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "bison.tab.h"
    extern int line;
%}

%%

"\n" {line++;}

";" {return SEMICOLON;}

"," {return COMMA;} 

"(" {return L_PARENTHESIS;}

")" {return R_PARENTHESIS;}

"[" {return L_REC_BRACKET;}

"]" {return R_REC_BRACKET;} 

"{" {return L_CURLY_BRACKET;}

"}" {return R_CURLY_BRACKET;}

"?" {return QUESTION_MARK;}

":" {return COLON;}

"." {return DOT;}

"&" {return AND;}

"*" {return STAR;}

"+" {return PLUS;}

"-" {return MINUS;}

"!" {return EXCLAMATION_MARK;}

"/" {return SLASH;}

"%" {return PERCENT;}

"<" {return LESS;}

">" {return GREATER;}

"<=" {return LESS_EQUAL;}

">=" {return GREATER_EQUAL;}

"==" {return EQUAL;}

"!=" {return NOT_EQUAL;}

"&&" {return LOGIC_AND;}

"||" {return LOGIC_OR;}

"++" {return UN_PLUS;}

"--" {return UN_MINUS;}

"=" {return EQ;}

"*=" {return MUL_EQUAL;}

"/=" {return DIV_EQUAL;}

"%=" {return MOD_EQUAL;}

"+=" {return PLUS_EQUAL;}

"-=" {return MINUS_EQUAL;}

"true" {return TRUE;}

"false" {return FALSE;}

"NULL" {return NUL;}

[0-9] {return NUMBER;}

[a-zA-Z][a-zA-Z0-9]* {return WORD;}

[a-zA-Z0-9]+ {return T_WORD;}

. {;}

%%

With bison -d bison.y I get the message : conflicts: (a number) shift/reduce conflicts.

For example I have with bison -v bison.y:

state 71

   54 expression: expression . L_REC_BRACKET expression R_REC_BRACKET
   58           | expression . unitary_op_assig
   59           | expression . binary_op_assig expression
   61           | expression . QUESTION_MARK expression COLON expression
   64           | DELETE expression .

    L_REC_BRACKET  shift, and go to state 75
    QUESTION_MARK  shift, and go to state 76
    UN_PLUS        shift, and go to state 43
    UN_MINUS       shift, and go to state 44
    EQ             shift, and go to state 77
    MUL_EQUAL      shift, and go to state 78
    DIV_EQUAL      shift, and go to state 79
    MOD_EQUAL      shift, and go to state 80
    PLUS_EQUAL     shift, and go to state 81
    MINUS_EQUAL    shift, and go to state 82

    L_REC_BRACKET  [reduce using rule 64 (expression)]
    QUESTION_MARK  [reduce using rule 64 (expression)]
    UN_PLUS        [reduce using rule 64 (expression)]
    UN_MINUS       [reduce using rule 64 (expression)]
    EQ             [reduce using rule 64 (expression)]
    MUL_EQUAL      [reduce using rule 64 (expression)]
    DIV_EQUAL      [reduce using rule 64 (expression)]
    MOD_EQUAL      [reduce using rule 64 (expression)]
    PLUS_EQUAL     [reduce using rule 64 (expression)]
    MINUS_EQUAL    [reduce using rule 64 (expression)]
    $default       reduce using rule 64 (expression)

    unitary_op_assig  go to state 83
    binary_op_assig   go to state 84
  • Please post the errors and warnings you are getting – Erik W May 29 '17 at 21:43
  • Welcome to Stack Overflow. Please read the [About] and [Ask] pages soon, but even more importantly, please read about how to create an MCVE ([MCVE]). You've done a lot with providing the code; you've not provided samples of the error messages. The `unitary_op_assig` has me puzzled. I'd probably go about this by removing rules from `expression` (and any consequential changes to eliminate now unused rules), until it compiles clean. Then I'd add back the last removed rule and study the verbose output from Bison to work out what's wrong. You really need to include some of that information. – Jonathan Leffler May 29 '17 at 21:46
  • 2
    You have all kinds of expressions in a single rule, but don't specify their precedence and associativity anywhere. You either need to split `expression` up into multiple rules, organized by precedence (see e.g. the C yacc grammar for an example of that) or use the `%left` and `%right` annotations to specify the precedence and associativity. – sepp2k May 29 '17 at 22:02
  • @anna_jennifer Not trying to be glib, but if all you tell me is that you tried `%left` and `%right`, all I can tell you is that you may have used them wrong. You need to show what you've tried and what errors and conflicts you got when trying that, so we can tell you why it did not work. Ideally you first simplify your grammar enough, so that only a few conflicts remain. – sepp2k May 30 '17 at 12:57
  • Sorry... i found out how to show the conflicts.. i posted an example – anna_jennifer May 31 '17 at 13:24
  • @anna_jennifer You'll probably need to "inline" your definitions of the operator rules (such as `binary_op`, `binary_op_assig` etc.) in order for the precedence annotations to have an effect. Alternatively you could probably use a `prec` annotation, but then all binary operators would end up having the same precedence. Some parser generators have the ability to declare inline rules to work around this, but I don't think bison has anything comparable. – sepp2k May 31 '17 at 15:32
  • thank you! i'll try to figure it out with the help of what you told me! :) – anna_jennifer May 31 '17 at 15:59
  • There are too many errors here to provide a simple fix recipe. I'd suggest you start with a simple grammar and work your way up. Precedence (left or right) is not your problem yet. Obvious errors are: your "programme" non-terminal resolves to another, single non-terminal "expression". You don't need "programme", you can start with "expression". You are missing DELETE token declaration, "%expect" clause suppresses the error messages, better to remove it,... etc – Sokre May 31 '17 at 18:38

0 Answers0