1
votes

I have a lexer and parser for the c language but I dont understand why
there is a syntax error for the given input

this is the lexer file

   %option yylineno
%{
#include "y.tab.h"
#include <stdio.h>

%}

DIGIT   [0-9]+
ID  [a-zA-Z][a-zA-Z0-9_]*

%%
"/*"([^\*\n\r]*) {printf("Non-terminated comments, Line Number: %d\n",yylineno);}
[/*]+[/*][a-zA-Z0-9]*[*/]+[*/]  {printf("<Comment, %s, %d>\n", yytext,yylineno);}
"if"                    {printf("<keyword, %s, %d>\n", yytext,yylineno); yylval = *yytext; return IF ;}
"else"                  {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return ELSE;}
"for"                   {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return FOR;}
"begin"                 {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"end"                   {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"procedure"             {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"function"              {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"void"                  {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return VOID;}
"main"                  {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"int"                   {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return INT;}
"float"                 {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return FLOAT;}
"printf"                {printf("<keyword, %s, %d>\n", yytext,yylineno ); }
"while"                 {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return WHILE;}
"char"                  {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return CHAR;}
"switch"                {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return SWITCH;}
"case"                  {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return CASE;}
"default"               {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return DEFAULT;}
"break"                 {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return BREAK;}
"do"                    {printf("<keyword, %s, %d>\n", yytext,yylineno );yylval = *yytext; return DO;}
"continue"              {printf("<keyword, %s, %d>\n", yytext,yylineno ); yylval = *yytext;return CONTINUE;}
"return"                {printf("<keyword, %s, %d>\n", yytext,yylineno ); yylval = *yytext;return RETURN;}
"+"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ADD;}
"-"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return SUBTRACT;}
"*"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return MULTIPLY;}
"/"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return DIVIDE;}
"<"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return LESSTHAN;}
">"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return GREATERTHAN;}
"++"                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return INCREMENT;}
"--"                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return DECREMENT;}
"="                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ASSIGN;}
"=="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ISEQUALTO;}
">="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return GREATERTHANEQUALTO;}
"<="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return LESSTHANEQUALTO;}
"%"                 {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return MODULUS;}
"!="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ISNOTEQUALTO;}
"+="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ADDANDASSIGN;}
"-="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return SUBTRACTANDASSIGN;}
"*="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return MULTIPLYANDASSIGN;}
"/="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return DIVIDEANDASSIGN;}
"%="                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return MODULUSANDASSIGN;}
"?:"                    {printf("<operator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return CONDITIONALOPERATOR;}
","                 {printf("<Comma, %s, %d>\n", yytext,yylineno );yylval = *yytext;return COMMA;}
";"                 {printf("<Terminator, %s, %d>\n", yytext,yylineno );yylval = *yytext;return ENDOFSTATEMENT;}
":"                 {printf("<Colon, %s, %d>\n", yytext,yylineno );yylval = *yytext;return COLON;}
"("                 {printf("<OpeningRoundBracket, %s, %d>\n", yytext,yylineno );return OPENINGROUND;}
")"                 {printf("<ClosingRoundBracket, %s, %d>\n", yytext,yylineno );return CLOSINGROUND;}
"{"                 {printf("<OpeningCurlyBracket, %s, %d>\n", yytext,yylineno );yylval = *yytext;return OPENINGBRACE;}
"}"                 {printf("<ClosingCurlyBracket, %s, %d>\n", yytext,yylineno );yylval = *yytext;return CLOSINGBRACE;}
"["                 {printf("<OpeningSquareBracket, %s, %d>\n", yytext,yylineno );yylval = *yytext;return OPENINGSQUARE;}
"]"                     {printf("<ClosingSquareBracket, %s, %d>\n", yytext,yylineno );yylval = *yytext;return CLOSINGSQUARE;}
[*]+{ID}+               {printf("<Pointer, %s, %d>\n", yytext,yylineno);}
{DIGIT}+                    {printf("<INTEGER, %s, %d>\n", yytext,yylineno);yylval = atoi(yytext);return INTEGER;}
{DIGIT}+"."{DIGIT}*             {printf("<FLOAT, %s, %d>\n", yytext,yylineno);yylval = atoi(yytext);return INTEGER ;}
["]+{ID}*[ ]*[:]*[;]*[(]*[)]*{ID}*["]+  {printf("<STRING, %s, %d>\n", yytext,yylineno);yylval = atoi(yytext);return REAL ;}
[']{ID}[']              {printf("<CHAR, %s, %d>\n", yytext,yylineno);yylval = *yytext;return CHARACTER ;}
[']{ID}{ID}+[']             {printf("CHAR constant too long: %s, Line Number: %d\n", yytext,yylineno);}
{ID}+                       {printf("<Identifier, %s, %d>\n", yytext,yylineno ); yylval = *yytext; return IDENTIFIER ;}
" "                 ;{printf("Space");}/* eat up whitespace */
"\t"                    ;/* eat up whitespace */
"\n"                ;/* eat up whitespace */
"#"                 {printf("Undefined Symbol: %s, Line Number: %d>\n", yytext,yylineno );}
"~"                 {printf("Undefined Symbol: %s, Line Number: %d>\n", yytext,yylineno );}
.                       printf( "Undefined Symbol: %s, %d\n",yytext,yylineno );
%%


int yywrap(){
    return 1;
}

The parser .y file

%{
#include <stdio.h>
#include <stdlib.h>
void yyerror();

FILE *f;
%} 

%token IF 
%token ELSE 
%token FOR 
%token VOID 
%token INT 
%token FLOAT 
%token WHILE 
%token CHAR 
%token SWITCH 
%token CASE 
%token DEFAULT 
%token BREAK
%token DO
%token CONTINUE
%token RETURN
%token ADD
%token SUBTRACT
%token MULTIPLY
%token DIVIDE
%token MODULUS
%token LESSTHAN
%token GREATERTHAN
%token INCREMENT
%token DECREMENT
%token ASSIGN
%token ISEQUALTO
%token GREATERTHANEQUALTO
%token LESSTHANEQUALTO
%token ISNOTEQUALTO
%token ADDANDASSIGN
%token SUBTRACTANDASSIGN
%token MULTIPLYANDASSIGN
%token DIVIDEANDASSIGN
%token MODULUSANDASSIGN
%token CONDITIONALOPERATOR
%token ENDOFSTATEMENT
%token COMMA
%token COLON
%token OPENINGROUND
%token CLOSINGROUND
%token OPENINGSQUARE
%token CLOSINGSQUARE
%token OPENINGBRACE
%token CLOSINGBRACE
%token INTEGER
%token REAL
%token CHARACTER
%token IDENTIFIER
%start TransitionUnit
%%

TransitionUnit : ExternalDeclaration TransitionUnit_a;

TransitionUnit_a : ExternalDeclaration TransitionUnit_a  
| /* NULL */
;

ExternalDeclaration : FunctionDefinition
|Declaration ENDOFSTATEMENT
;

FunctionDefinition : TypeSpecifier Declarator FunctionDefinition_a
|Declarator FunctionDefinition_b
;

FunctionDefinition_a : DeclarationList CompoundStatement
                        |CompoundStatement;

FunctionDefinition_b : DeclarationList CompoundStatement
                    |CompoundStatement
;

TypeSpecifier : VOID  
|CHAR 
|INT 
|FLOAT
;

Declarator : DirectDeclarator 
            |    Pointer DirectDeclarator;

DirectDeclarator : IDENTIFIER DirectDeclarator_a;

DirectDeclarator_a : OPENINGROUND DirectDeclarator_b 
                    |OPENINGSQUARE DirectDeclarator_c
                    |/* NULL */
                    ;

DirectDeclarator_b : Declarator CLOSINGROUND DirectDeclarator_a
                    |ParameterList CLOSINGROUND DirectDeclarator_a 
                    |CLOSINGROUND DirectDeclarator_a
                    ;

DirectDeclarator_c : CLOSINGSQUARE DirectDeclarator_a
|INT CLOSINGSQUARE DirectDeclarator_a
;

Pointer : MULTIPLY Pointer_a
;

Pointer_a : Pointer 
|/* NULL */
;

DeclarationList : Declaration ENDOFSTATEMENT DeclarationList_a
;

DeclarationList_a : Declaration ENDOFSTATEMENT DeclarationList_a 
|/* NULL */
;

Declaration : TypeSpecifier Declaration_a;

Declaration_a : InitDeclaratorList 
|/* NULL */
;

InitDeclaratorList : InitDeclarator InitDeclaratorList_a
;

InitDeclaratorList_a : COMMA InitDeclarator InitDeclaratorList_a 
|/* NULL */
;

InitDeclarator : Declarator InitDeclarator_a
;

InitDeclarator_a : ASSIGN Initializer 
|/* NULL */
;

Initializer : Constant
| OPENINGBRACE InitializerList Initializer_a
;

Initializer_a : CLOSINGBRACE
|COMMA CLOSINGBRACE
;

InitializerList : Initializer InitializerList_a
;

InitializerList_a : COMMA Initializer InitializerList_a 
|/* NULL */
;

ParameterList : ParameterDeclaration ParameterList_a;

ParameterList_a : COMMA ParameterDeclaration ParameterList_a 
|/* NULL */
;

ParameterDeclaration : TypeSpecifier ParameterDeclaration_a;

ParameterDeclaration_a : Declarator 
|/* NULL */;

CompoundStatement : OPENINGBRACE CompoundStatement_a;

CompoundStatement_a : CLOSINGBRACE
|StatementList CLOSINGBRACE
|DeclarationList CompoundStatement_b
;

CompoundStatement_b : StatementList CLOSINGBRACE
|CLOSINGBRACE
;

StatementList : Statement StatementList_a;

StatementList_a : Statement StatementList_a 
|/* NULL */
;

Statement : LabeledStatement
|CompoundStatement
|ExpressionStatement
|SelectionStatement
|IterationStatement
|JumpStatement;

LabeledStatement : CASE Constant COLON Statement
|DEFAULT COLON Statement;


ExpressionStatement : ENDOFSTATEMENT
|Expression ENDOFSTATEMENT
;

SelectionStatement : IF OPENINGROUND Expression CLOSINGROUND Statement SelectionStatement_a
|SWITCH OPENINGROUND Expression CLOSINGROUND Statement;

SelectionStatement_a : ELSE Statement 
|/* NULL */
;

JumpStatement : CONTINUE ENDOFSTATEMENT
|BREAK ENDOFSTATEMENT
|RETURN JumpStatement_a
;

JumpStatement_a : Expression ENDOFSTATEMENT;

IterationStatement : WHILE OPENINGROUND Expression CLOSINGROUND Statement
|DO Statement WHILE OPENINGROUND Expression CLOSINGROUND ENDOFSTATEMENT
|FOR OPENINGROUND Expression ENDOFSTATEMENT Expression ENDOFSTATEMENT Expression CLOSINGROUND Statement
;

ConditionalExpression : EqualityExpression ConditionalExpression_a;

ConditionalExpression_a : CONDITIONALOPERATOR Expression COLON ConditionalExpression 
| 
;

Expression : AssignmentExpression Expression_a;

Expression_a : COMMA AssignmentExpression Expression_a 
| 
;

AssignmentExpression : ConditionalExpression
|UnaryExpression AssignmentOperator AssignmentExpression;

EqualityExpression : RelationalExpression EqualityExpression_a;

EqualityExpression_a : ISEQUALTO RelationalExpression EqualityExpression_a '\n'
|ISNOTEQUALTO RelationalExpression EqualityExpression_a
| 
;

RelationalExpression : AdditiveExpression RelationalExpression_a;

RelationalExpression_a : LESSTHAN AdditiveExpression RelationalExpression_a '\n'
|GREATERTHAN AdditiveExpression RelationalExpression_a
|LESSTHANEQUALTO AdditiveExpression RelationalExpression_a
|GREATERTHANEQUALTO AdditiveExpression RelationalExpression_a
| 
;

AdditiveExpression : MultiplicativeExpression AdditiveExpression_a;

AdditiveExpression_a : ADD MultiplicativeExpression AdditiveExpression_a '\n'
|SUBTRACT MultiplicativeExpression AdditiveExpression_a
|
;

MultiplicativeExpression : UnaryExpression MultiplicativeExpression_a;

MultiplicativeExpression_a : MULTIPLY UnaryExpression MultiplicativeExpression_a '\n'
| DIVIDE UnaryExpression MultiplicativeExpression_a
| MODULUS UnaryExpression MultiplicativeExpression_a
| 
;

AssignmentOperator : ASSIGN
| ADDANDASSIGN
| SUBTRACTANDASSIGN
| MULTIPLYANDASSIGN
| DIVIDEANDASSIGN
| MODULUSANDASSIGN
;

Constant : INTEGER
| CHARACTER
| REAL
;

UnaryExpression : PostFixExpression
| INCREMENT UnaryExpression
| DECREMENT UnaryExpression
;

PostFixExpression : PrimaryExpression PostFixExpression_a;

PostFixExpression_a : OPENINGSQUARE Expression CLOSINGSQUARE PostFixExpression_a '\n'
| OPENINGROUND PostFixExpression_b
| INCREMENT PostFixExpression_a
| DECREMENT PostFixExpression_a
|
;

PostFixExpression_b : ArgumentExpressionList CLOSINGROUND PostFixExpression_a
| CLOSINGROUND PostFixExpression_a
;

ArgumentExpressionList : AdditiveExpression ArgumentExpressionList_a;

ArgumentExpressionList_a : COMMA AdditiveExpression ArgumentExpressionList_a '\n'
| 
;

PrimaryExpression : IDENTIFIER { fprintf(f, "Got an %s",yylval);}
| Constant
;
%%

void yyerror(char *s){
    extern int yylineno;
    printf("%s at line no. %d",s,yylineno);
}

int main(){
    extern FILE *yyin;
    yyin = fopen("input.txt","r");

    f = fopen("output.txt","w");
    fprintf(f,"Adha Hogaya");
    yyparse();

    return 1;
}

The input file which is to be parsed

int i;
int a;
void main(){
}

The code parses fine until the '(' after which it displays a
syntax error. I do not understand what is the problem some help would
be appreciated

the code is compiled through the following commands

flex 'filename'.l  
bison -dy 'filename'.y  
gcc lex.yy.c y.tab.c -o 'filename'.exe
1
Your language is too complexfor us to quickly see where you made an error. - Paul Ogilvie
It seems your language does not allow an empty parameter list. - Paul Ogilvie

1 Answers

1
votes

Your scanner ignores the "keyword" main (since it doesn't return anything).

"main"                  {printf("<keyword, %s, %d>\n", yytext,yylineno ); }

It's not clear to me why you would want main to be a keyword, since your grammar doesn't seem to allow functions whose names are not identifiers.


Really, that scanner definition is full of problems, most of which are not relevant to this question. But you really should take a look at some example scanner definitions and (re-)read the flex manual. For a start, you would be well advised to use single-character tokens ({ instead of OPENINGBRACE) which make both your scanner and your parser much more readable. But you need to take a careful look at a number of your scanner patterns, particularly the comment pattern and the string/character literal patterns. Your ID macro is not a single character, so the use of {ID}+ in other patterns is certainly wrong (and results in a flex warning).

Both flex and bison provide debugging trace features, which are much easier than filling your source code with printf statements. If you'd just used those traces, you would have immediately seen that the "keyword" main is not being sent to the parser. See the debugging sections of the flex manual and the bison manual.

And your grammar file looks like you're trying to write a grammar suitable for an LL(1) (recursive-descent) parser. That is totally unnecessary -- bison/yacc is an LALR(1) parser generator, which handles left-recursion just fine -- and makes your grammar much less readable. Consider the difference between the simple:

Prototype:     '(' ')'
         |     '(' ParameterList ')'
ParameterList
         :     ParameterDeclaration
         |     ParameterList ',' ParameterDeclaration;
ParameterDeclaration
         :     TypeSpecifier
         |     TypeSpecifier Declarator

Finally, you'll need to fix your semantic value type; yylval = *yytext is very rarely useful. (It is not necessary to set yylval for a token which has no semantic value.) The default int type does not allow you to pass strings (identifiers or string literals) to your scanner, where they would probably be useful.