3
votes

I keep getting "segmentation fault: 11" when I compile my code on Mac but it works fine on Windows, I would be really grateful if you could take a look at it and help me solve the problem. Thanks in advance, Francis :D

mylang.l Code:

    %{

#include <stdio.h>
#include <string.h>
#include "lang.tab.h"

int lineno = 1;

%}
%%

"print"                     return PRINT;
[0-9]+                      yylval=atoi(yytext); return NUMBER;
\".*\"                      yylval=strdup(yytext); return STRING;
\"                          return QUOTE;
\;                          return SEMICOLON;
[a-zA-Z][a-zA-Z0-9]*        lineno++; yylval=strdup(yytext); return VARIABLE;
[\n]                        ;
"/*"([^*]|\*+[^*/])*\*+"/"  ;
[ \t]                       ;

"="                         return EQUALS;
"+"                         return PLUS;
"-"                         return MINUS;
"*"                         return MUL;
"/"                         return DIVIDE;
"%"                         return MODULUS;

.                           { printf("Error on line: %d", lineno); return 1; }

%%

mylang.y Code:

    %{
#include <stdio.h>
#include <string.h>
#include <math.h>

extern FILE *yyin; /* Input for yacc parser. */
#ifdef YYTEXT_POINTER
extern char *yytext; /* Current symbol for error reporting. */
#else
extern char yytext[];
#endif
extern int yylex(void); /* Lexical analyzer function. */
extern int yyparse(void); /* Parser function. */

int yydebug=0;

void yyerror(const char *str)
{
    fprintf(stderr,"error: %s\n",str);
}

int yywrap()
{
    return 1;
}


int main(int argc, char *argv[]) {
    if (argc > 1)
        {
        yyin = fopen(argv[1], "r");
        yyparse(); /* Calls yylex() for tokens. */
        }
    else
        printf("syntax: %s filename\n", argv[0]);
    return 0;
    }

/* Custom functions for language will go here*/


/* and end here */
%}

%token PRINT 
%token QUOTE 
%token SEMICOLON 
%token STRING
%token NUMBER
%token EQUALS
%token VARIABLE

%token PLUS
%token MINUS
%token MUL
%token DIVIDE
%token MODULUS

%left PLUS MINUS
%left MUL DIVIDE MODULUS

%start program       

%%

program:        /* empty */
                |
                program line
                ;

line:           stmt
                ;

end_stmt:       SEMICOLON
                ;

expr:           NUMBER
                { $$ = $1; }
                |
                expr PLUS expr
                { $$ = $1 + $3; }
                |
                expr MINUS expr
                { $$ = $1 - $3; }
                |
                expr MUL expr
                { $$ = $1 * $3; }
                |
                expr DIVIDE expr
                { $$ = $1 / $3; }
                |
                expr MODULUS expr
                { $$ = $1 % $3; }
                ;

var:            VARIABLE
                { $$ = $1; }
                ;

var_assignment: var EQUALS expr
                { varCounter($1); updateSymbolTable($1);  }
                ;

stmt:           print_stmt end_stmt
                |
                var_assignment end_stmt
                ;

print_stmt:     PRINT STRING
                { printf("%s", $2); }
                |
                PRINT expr
                { printf("%d", $2); }
                ;

%%
1
Well, what line of code is causing the error? Did you try running the program in a debugger? That is the first step. - OldProgrammer
Oh sorry, I did a little debugging myself and I think the problem is something to do with the STRING token in the Bison file. When the program gets the the "print_stmt: PRINT STRING" line it throws the segmentation fault, When I execute the program and give it the input "print 1;" it works as expected but when I give it the input 'print "Hello World";' it gives the segmentation fault. Thanks again, Francis - Francis
By the way, lineno++; is in the wrong place. I presume you want to increment lineno when you see a newline; not when you see an identifier. - rici

1 Answers

4
votes

You're making the assumption that yylval can contain either a pointer (to a string) or an integer. The default type for yylval is int, so on a platform where a pointer is the same size as an integer, things will work fine. On a platform where pointers are bigger, the pointer will be corrupted and attempting to dereference it will lead to a segfault.

Don't you get compile warnings?