Unable to find cause of 'syntax error' in Bison code - syntax

I'm trying to connect simple flex and bison code that would just recognize a character for now. Yet I'm facing this error. I've read through a lot of answers to figure out what is wrong but am lost. Any help would be highly appreciated as I'm just starting out to explore this and could not find a lot of resources for it.
This is my .l file
%{
#include <stdlib.h>
#include <stdio.h>
#include "MiniJSC.tab.h"
void yyerror (char *s);
int yylex();
%}
%%
[0-9]+ { yylval.num = atoi(yytext); return T_INT_VAL; }
%%
int yywrap (void) {return 1;}
my .y file
%{
void yyerror (char *s);
int yylex();
#include <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
%}
%union {int num; char id;} /* Yacc definitions */
%start line
%token print
%token T_INT_VAL
%type <num> line
%type <num> term
%type <num> T_INT_VAL
%%
/* descriptions of expected inputs corresponding actions (in C) */
line : print term ';' {printf("Printing %d\n", $2);}
;
term : T_INT_VAL {$$ = $1;}
;
%% /* C code */
void yyerror (char *s) {
fprintf (stderr, "%s\n", s);
}
int main (void) {
return yyparse ( );
}
The compilation and output:
$ bison MiniJSC.y -d
$ lex MiniJSC.l
$ gcc lex.yy.c MiniJSC.tab.c
$ ./a.out
10
syntax error
$

line : print term ';'
According to this, a valid line contains a print token followed by a term. Since a term must be a T_INT_VAL token, that means a valid line is a print token followed by a T_INT_VAL token.
Your input consists only of a T_INT_VAL token, so it is not a valid line and that's why you get a syntax error.
Also note that your lexer never produces a print token, so even if you entered print 10 as the input, it'd be an error since the lexer isn't going to recognize print as a token. So you should add a pattern for that as well.
You should also rename print to match your naming convention for tokens (i.e. ALL_CAPS).

Related

Can someone tell me why I'm getting this error? How can I fix it? "collect2: error: ld returned 1 exit status"

This is a header file that I'm getting the error on.
#include <vector>
#include <fstream>
#ifndef CRYPTO_H
#define CRYPTO_H
// given a char c return the encrypted character
char encrypt(char c);
// given a char c retun the decrypted character
char decrypt(char c);
// given a reference to an open file, return a vector with the # of characters, words, lines
std::vector<int> stats(std::ifstream& infile);
#endif
Please let me know what you think.
Thanks!!

Have GCC give warnings for the preprocessed file

GCC shows line numbers for the .c file, which in my case is a macro that is defined using other macros, which are defined using even more macros, etc. Is there a way to have GCC give the line numbers for the preprocessed .i file instead?
bla.c
#include <stdlib.h>
#include <stdio.h>
#define PRINT(a) printf("%d\n", (a));
int main()
{
double a = 2.5;
PRINT(a);
return 0;
}
It will print the warning for the line containing PRINT(a) (line 10), but I want it to print the line containing printf("%d\n", (a));; from the preprocessed file (line 1837)
preprocessed file:
<other code above>
int main()
{
double a = 2.5;
printf("%d\n", (a));;
return 0;
}
Use the options -no-integrated-cpp -P to get:
/tmp/ccQ2ECah.i: In function 'main':
/tmp/ccQ2ECah.i:729:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]
729 | printf("%d\n", (a));;
| ~^ ~~~
| | |
| int double
| %f
The -no-integrated-cpp option causes the preprocessor and compiler to run as truly separate passes, where the only communication between them is the preprocessor output.
In this mode, the preprocessor would normally include #line directives in its output to identify source line numbers from the original file. The -P option suppresses them. Then the compiler pass has no information about the original file's line numbers, and can only print the line numbers of the preprocessor output.

sed replace text at based on line number dynamically

I am looking for bash script comments from // to /* */
I got partial working
sed -i '14s/////*/' a.c
this is working like // with */ how to add */ at the end.
Originl script
#include <stdio.h>
char buffer[10] = {'0'}; // comment1
int main()
{
printf("Hello World"); // Comment2
return 0;
}
Expected file
#include <stdio.h>
char buffer[10] = {'0'}; /* comment1 */
int main()
{
printf("Hello World"); /* Comment2 */
return 0;
}
Simplest solution
Assuming the idiosyncratic spacing in the desired output shown in the question is unintentional:
sed 's%// *\(.*\)%/* \1 */%'
The keys here are:
Using % instead of / to mark the separate parts of the s/// (or s%%%) command.
Capturing the text of the comment in \(…\).
Replacing it with \1 (preceded by /* and followed by */ and single spaces.
Working on a direct copy of the data from the question, the output is:
#include <stdio.h>
char buffer[10] = {'0'}; /* comment1 */
int main()
{
printf("Hello World"); /* Comment2 */
return 0;
}
Improving the handling of spaces
There are trailing blanks after the comments — ugly! We can fix that with care:
sed 's%//[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$%/* \1 */%'
That matches zero or more spaces after the // opening the comment, and matches up to the last non-space before an optional string of spaces at the end of the line. That generates:
#include <stdio.h>
char buffer[10] = {'0'}; /* comment1 */
int main()
{
printf("Hello World"); /* Comment2 */
return 0;
}
And you can deal with all trailing white space first, which is probably a good idea anyway, using:
sed -e 's/[[:space:]]\{1,\}$//' -e 's%//[[:space:]]*\(.*\)%/* \1 */%'
which yields:
#include <stdio.h>
char buffer[10] = {'0'}; /* comment1 */
int main()
{
printf("Hello World"); /* Comment2 */
return 0;
}
That differs from the previous output by not having a space after main().
Proper comment handling is hard!
Note that this simple code can easily be confused by valid C, such as:
printf("// this is not a comment\n");
To understand C fully enough not to make that mistake is beyond sensible sed. Less seriously, it will miss some valid but implausible character sequences that are officially comments, such as:
/\
/this is a comment\
and this is also part of the comment\
even with extra spaces
and if you allow trigraphs (don't), then:
/??/
/??/
This is part of the comment started two lines before!
This sort of stuff shouldn't afflict any actual code base, but are the sorts of garbage that compiler writers have to handle correctly.

request for member " " in something not a structure or union? in Flex&Bison

in my final project left me several codes, one of them is this for flex & bison.
The problem is that gcc returns me the message "request for member 'db' in something not a structure or union" in bison file ...
I do not know how to fix this, I find examples of solutions but none works for me.
I hope I can help, thanks in advance.
Flex file:
%{
#include <stdlib.h>
#include "y.tab.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
%}
%option noyywrap
%option yylineno
digit [0-9]
blank [\t]
sign [+-/*]
other .
%%
{digit}+ { sscanf(yytext, "%lf", &yylval.db); return NUMBER;}
{digit}+\.{digit}* { sscanf(yytext, "%lf", &yylval.db); return NUMBER;}
\.{digit}+ { sscanf(yytext, "%lf", &yylval.db); return NUMBER;}
sign return *yytext;
{blank}+ ;
{other} return yytext[0];
%%
int main()
{
if (yyparse()==0){
printf("\n NO ERROR");}
return 0;
}
int yyerror(char * mensaje)
{
printf("\n AND STOP");
printf("\n ERROR: %s",mensaje);
printf("\n ERROR LINE: %d",yylineno);
return 0;
}
Bison File:
%{
#include <stdio.h>
#include <stdlib.h>
char result[100];
%}
%union { double db; int i; }
%token NUMBER
%left '-' '+'
%left '*' '/'
%left '(' ')'
%nonassoc UMINUS
%type<db> list NUMBER
%type<i> expression
%start list
%%
list : expression { printf("\nResultado: %5g\n",$$.db);}
;
expression : expression '+' expression { $$.db = $1.db + $3.db; }
| expression '-' expression { $$.db = $1.db - $3.db; }
| expression '*' expression { $$.db = $1.db * $3.db; }
| expression '/' expression { if ($3.db==(double)0) yyerror("Division por cero\n");
else $$.db = $1.db / $3.db; }
| '-' expression %prec UMINUS { $$.db = -$2.db; }
| '(' expression ')' { $$.db = $2.db; }
| NUMBER { $$.db = $1.db; }
;
When you declare that expression has type i (%type<i> expression), you're telling bison that wherever you've put an expression, the stack value should be the .i variant. So in all of the expression productions, $$ already represents the .i union member; if you write an explicit .db, then you end up generating yylval.i.db. But yylval.i is an int, which is not a strut or a union and therefore cannot have any members.
I strongly suspect that you intended the type of expression to be db, but whatever it is, you don't have to (and in fact cannot) explicitly specify the union member in your action.

bison parser compilation unkonwn errors

I am building a parser but I have some errors that I could not solve them, I am nuw to bison and flex, please help me solve them and understand why they are happening here is my errors that I get:
lexical.l:3:20: error: common.h: No such file or directory
In file included from lexical.l:5:
bison.tab.h:81: error: expected â=â, â,â, â;â, âasmâ or â__attribute__â before âyylvalâ
bison.tab.c:1155: error: conflicting types for âyylvalâ
bison.tab.h:81: note: previous declaration of âyylvalâ was here
bison.y: In function âyyparseâ:
bison.y:96: error: incompatible types when assigning to type âSTYPEâ from type âNODEPTRâ
here is my parser file bison.y:
%{
#include <stdio.h>
#include "bison.tab.h"
#include "common.h"
//int yylex();
void yyerror (char const *);
typedef struct STYPE {
NODEPTR pointer;
} STYPE;
#define YYSTYPE STYPE
%}
/* Bison declarations. */
%token ELSE REAL INTEGER XWRITE WHILE END DO IF THEN XPROGRAM FUNCTION XRETURN XREAD VAR FOR XBEGIN CALL ID NUM
%token RELOP ADDOP MULOP ASSIGN AND OR NOT
%left '-' '+'
%left '*' '/'
%nonassoc LOWER_THAN_ELSE
%nonassoc ELSE
If you #define YYSTYPE in your bison file, you need to #define YYSTYPE also in your flex file, because bison doesn't put the #define into the generated header file. You need to do this before you #include the generated header file.
Bison doesn't put the #define in the generated header because it has no way of knowing whether you did, since you might do it in an included file. In fact, if you're going to #define YYSTYPE, you should do it in a common header file, and #include the common header file in both bison and flex programs (as above, before you include the bison-generated header file).
Also, when you're regenerating the generated code, remember to always generate the bison program first because the flex program depends on the generated header file. That's the opposite order to the way you are doing it.
Just to make all this a bit clearer, here's an example:
common.h:
struct MyType {
/* ... /
};
#define YYSTYPE struct MyType;
lexer.l:
%{
/* All your standard includes go here */
/* Must go in this order */
#include "common.h"
#include "bison.tab.h"
%}
bison.y:
%{
/* Whatever library includes you need */
#include "common.h"
/* Don't include bison.tab.h; it will get inserted automatically */
%}
To fix the yytext error add this to bison.y :-
extern char *yytext
To fix the yyerror error make your prototype at the top of bison.y match the defn below :-
int yyerror(const char *message);
Fixing the yylval error requires a little more work and I don't understand this well enough to help. I'd suggest trying a simple hello,world type lexer,parser and move forward from there.
Here is the common.h I used :-
typedef struct STYPE {
int pointer;
} STYPE;
And the header of lexer :-
%{
#include "common.h"
#define YYSTYPE STYPE
#include <stdio.h>
#include"bison.tab.h"
void showToken(char*);
%}
And the header of parser :-
%{
#include <stdio.h>
#include "common.h"
extern char *yytext;
#define YYSTYPE STYPE
%}
This gives me one error and a few warnings but those are due to the undefined functions. Note that I have moved the declaration of STYPE to the top of lexer and parser

Resources