How to Implement Type Checking in Yacc/Bison and C?

  • Thread starter -EquinoX-
  • Start date
In summary, the speaker is trying to access the type of $1 and $2 in their yacc code, but is having trouble with it. They have defined a struct and a %union in their code and are using various expressions to check for specific types. They also mention using %union to access the type through yylval in lex. The $'s in their code represent parts of a recursive tree and are received from lex, not yacc.
  • #1
-EquinoX-
564
1
Ok, so first I want to do a type checking to my yacc code. The partial code I have is below:

What must I add to the code so that I can access $1.type? I already defined:

typedef struct Type{
int type;
} Type

%union{
int typ;
}

%type <typ> expr

However it still doesn't work


Code:
expr   : '-' expr %prec UNARY {$$ = -$2}
       | '!' expr %prec UNARY {$$ = !$2 }
       | expr '+' expr { 
          if ($1.type != INTEGER || $3.type != INTEGER)
          {
                fprintf(stderr, "Invalid type for addition, must be an integer\n");
          }
          else
                 $$.type = INTEGER;
        }
       | expr '-' expr {
          if ($1.type != INTEGER || $3.type != INTEGER)
          {
                fprintf(stderr, "Invalid type for substraction, must be an integer\n");
          }
          else
                 $$.type = INTEGER;
        }
       | expr '*' expr { 
          if ($1.type != INTEGER || $3.type != INTEGER)
          {
                fprintf(stderr, "Invalid type for multiplication, must be an integer\n");
          }
          else
                 $$.type = INTEGER;
        }
       | expr '/' expr { 
          if ($1.type != INTEGER || $3.type != INTEGER)
          {
                fprintf(stderr, "Invalid type for division, must be an integer\n");
          }
          else
                 $$.type = INTEGER;
        }
       | expr EQ expr 
       | expr NE expr
       | expr LE expr
       | expr '<' expr
       | expr GE expr
       | expr '>' expr
       | expr AND_OP expr
       | expr OR_OP expr
       | ID opt_idexpr
       | '(' expr ')'
        | '(' error {fprintf(stderr, "Missing expression after '(' \n");}
       | INTCON {
                  $1.type = INTEGER;
                  }
       | CHARCON {
                  $1.type = CHARMARK;
                  }
       | STRINGCON {
                $1.type = STRINGMARK;
                  } 
        
;


All I want to do here is so that I can do $1.type or $2.type, so therefore I know what type is $1 or $2 and the type is basically something that I have defined in top of the file, something like:

#define INTEGER 1
#define CHAR 2
 
Technology news on Phys.org
  • #2
When you create %union, it's your yylval variable in lex. Hence when your make actions for the regular expressions in lex you can access the type as yylval.type.
The $'s are the parts of your recursive tree, for i.e.
S:EXPR ',' EXPR2
$1 = EXPR
$2 = ,
$3 = EXPR2
$$ = S

you receive those from lex not from yacc.
 
  • #3

#define STRING 3


To access $1.type, you need to add a declaration for it in the %union section and also specify it as the return type for the <expr> rule. In this case, it looks like you have already done that with the line "%type <typ> expr". However, you also need to assign the type to $$.type in each rule where $1 or $2 is used to ensure that the type is properly propagated through the expression. For example, in the rule for addition, you would need to add the line "$$.type = $1.type;" after the if-else statement. This will assign the type of the first expression to the result of the addition.

Additionally, you may want to consider using a switch statement instead of multiple if-else statements for better readability and maintainability. You could also use the %type directive to specify the return type for each individual operator, rather than for the entire <expr> rule. This would make your code more modular and easier to debug.

Finally, make sure that you have properly defined the Type struct and that it is included in your yacc/bison file. Without the proper definitions, the type checking will not work.
 

FAQ: How to Implement Type Checking in Yacc/Bison and C?

What is Yacc/bison and how is it related to C?

Yacc and Bison are both computer programs that are used to generate parsers, which are tools that analyze and interpret the structure of a language. They are commonly used in conjunction with the C programming language to create compilers and interpreters.

What are some common problems encountered when using Yacc/bison with C?

Some common problems include syntax errors in the grammar file, conflicts between rules, and difficulty with debugging due to the complexity of the generated code. Other issues may arise from incorrect use of C data types or memory management.

Can Yacc/bison be used with languages other than C?

Yes, Yacc and Bison can be used with other programming languages such as C++, Java, and Python. However, some modifications may be necessary depending on the specific language and its syntax.

How can I debug Yacc/bison and C code?

Debugging Yacc/bison and C code can be challenging due to the complexity of the generated code. One approach is to use a debugger specifically designed for this purpose, such as GNU Debugger (GDB). Another option is to insert printf statements in the code to trace the program's execution.

Are there any alternatives to Yacc/bison for parsing?

Yes, there are several alternatives to Yacc/bison, such as ANTLR, Flex, and Lemon. These programs offer similar functionality but may have different approaches or syntax. It is recommended to research and compare different options to determine the best fit for a specific project.

Back
Top