I'm just starting with flex and i have some concerns about this tool.
%{
#include "parser.h"
int line_num = 1;
%}
\n { line_num++; }
%%
In the above code i'm just counting the lines in my scanning file, right?
How could I call the line_num value from another .c document? Whit a function like:
int getLineNumber(void);
And also, how could I detect lexical errors with this tool? I know that it is with the ".*" pattern but how to print it(in a function on a different .c again) like:
printf ("%d: error: %s\n", getLineNumber(), message);
Thanks.
In the code you've shown, you're already defining a global variable line_num. Just declare extern int line_num; in your header file and you can access it anywhere in your program.
If you want to avoid the global variable, replace the beginning of your scanner with something like:
%{
#include "parser.h"
static int line_num = 1;
int getLineNumber(void) {
return line_num;
}
%}
And put a declaration for the getLineNumber function in your header. (This is just ordinary C stuff, flex doesn't add anything weird here.)
For error handling, you can add a rule like:
. { reportUnrecognizedToken(); }
And then put a function like this somewhere:
void uncrecognizedToken() {
printf("Unrecognized token on line %d\n", getLineNumber());
exit(1);
}
Related
Bison always prints the input instead of running the action.
I begin with Bison and I try to make it working with the simpler rule as possible.
Lexer
%{
#include <stdio.h>
#include "wip.tab.h"
%}
%%
[\t\n ]+ ;
[a−z]+ { yylval.sval = strdup(yytext); return IDENTIFIER;}
%%
Parser
%{
#include <stdio.h>
#include <stdlib.h>
int yylex(void);
void yyerror(char const *);
FILE *yyin;
%}
%union{
char *sval;
}
%token IDENTIFIER
%%
input:
%empty
| input line
;
line:
'\n'
| IDENTIFIER {printf("OK\n");}
;
%%
int main(void) {
FILE *myfile = fopen("example.wip", "r");
if (!myfile) {
printf("File can't be opened\n");
return -1;
}
yyin = myfile;
yyparse();
}
void yyerror(char const *s) {
fprintf(stderr, "%s\n", s);
}
The "example.wip" input file
hello
I expect the "OK" output in my terminal but the parser just prints the content of the file.
Thanks in advance.
Bison always prints the input instead of running the action.
Bison-generated never print the input unless that's what the actions say. Since none of your actions print anything other than "OK", that can't be what's going on here.
However, by default flex-generated lexers do print the input when they see a character that they don't recognize. To verify that this is what's going on, we can add a rule at the end of your lexer file that prints a proper error message for unrecognized characters:
. { fprintf(stderr, "Unrecognized character: '%c'\n", yytext[0]); }
And sure enough, this will tell us that all the characters in "hello" are unrecognized.
So what's wrong with the [a−z]+ pattern? Why doesn't it match "hello"? What's wrong is the −. It's not a regular ASCII dash, but a Unicode dash that has no special meaning to flex. So flex interprets [a−z] as a character class that can match one of three characters: a, the Unicode dash or z - not as a range from a to z.
To fix this, just replace it with a regular dash.
I'm still learning C and I understand that to get rid of most implicit declaration warnings, you add the prototype header at the beginning. But I'm confused as to what you do when you have outside methods being used in your code.
This is my code when I'm using the outside methods
#include <stdio.h>
#include <string.h>
int main(void)
{
int arrayCapacity = 10;
int maxCmdLength = 20;
int A[arrayCapacity];
int count = 0; /* how many ints stored in array A */
char command[maxCmdLength + 1];
int n;
while (scanf("%s", command) != EOF)
{
if (strcmp(command, "insert") == 0)
{
scanf("%d", &n);
insert (n, A, arrayCapacity, &count);
printArray(A, arrayCapacity, count);
}
else if (strcmp(command, "delete") == 0)
{
scanf("%d", &n);
delete(n,A,&count);
printArray(A, arrayCapacity, count);
}
else
{
scanf("%d", &n);
printArray(A, arrayCapacity, count);
}
}
return 0;
}
The methods printArray, insert, and delete are all in the form of: printArray.o, insert.o, delete.o
This is how I compiled my program: gcc -Wall insert.o delete.o printArray.o q1.c
and I get these warnings:
q1.c: In function âmainâ:
q1.c:20: warning: implicit declaration of function `insert'
q1.c:21: warning: implicit declaration of function `printArray'
q1.c:30: warning: implicit declaration of function `delete'
I've tried including this in headers but I get errors saying file or directory not found.
Any help appreciated.
Put them in a header file foo.h like so:
extern void printArray(int *A, int capacity, int count);
...
then include that file in your source
#include "foo.h"
You need to include the correct headers to get rid of such warnings.
If you get a "file not found" error, try to include them as
#include "myheader.h"
and put your header files in the same directory as your source code.
Generally speaking, #include "file" is for programmer-defined headers while #include <file> is or standard headers.
You should be able to just put in the function prototype at the top of the file like you do for other functions in the same file. The linker should take care of the rest.
Where did you get those .o files from? If you have written them yourself, then you should create the corresponding .h files. If you got these files from somewhere else, then you should search for the headers in the same place.
If all called functions are written before the main() function the compiler will know their name, return type and parameter signature and can match all three of these properties with each following function invocation.
Some programmers like to write a function signature first, and do the implementation at a later time.
The only time a function declaration is essential is when using co-routines: functionA invokes functionB which in turn invokes functionA.
Done as follows:
type a(...signatureOfA...)
/* compiler now knows about a() */
type b(...signatureOfB...)
{…
// implementation of b
a(…arguments for a…);
/* compiler knows about above */
…}
type a(...signatureOfA...)i
{…
// implementation of a
b(…arguments for b…);
/* compiler knows about above */
…}
int main()
{
a(… arguments for a…);
/* compiler knows */
return(code);
}
For example: If I have two .h files
process1.h and process2.h
and they contain two function with different output variables.
process1.h:
function(int var)
{
return 2*var;
}
process2.h:
function(int var)
{
return 10*var;
}
Can this be done in main.c:
int main()
{
int a = 2;
#include "process1.h"
printf("%d",function(a)); //output is 4
EXCLUDE #INCLUDE "process1.h" ????? <----can this be done in any way??
#include "process2.h"
printf("%d",function(a)); //output is 20
}
No, you cannot "un-include" a file. Think of all the preprocessor directives (lines starting with #) as happening before the actual C compiler even sees the source file. They just operate on the text of the file, and the preprocessor could be implemented as a separate step that just feeds new text into the actual compiler.
The best way to modify the actions of an include depending on the caller is to use further macros inside the included files, that you can #define before including them.
Still, your overall syntax is off, you can't (typically) nest functions in C.
No, and you should not try to write a program with two functions of the same name.
In the special case that the functions are actually defined in the header file (instead of just prototypes), you can do this:
#define function function_file1
#include "file1.h"
#undef function
#define function function_file2
#include "file2.h"
#undef function
int
main (void)
{
int a = 2;
printf ("%d\n", function_file1 (a));
printf ("%d\n", function_file2 (a));
}
BUT if you rename a function prototype then you haven't actually renamed the real function, so you'll get undefined symbol error when you link.
In any case, if you have two functions defined with the same name then it won't link anyway, not matter what else you do in the sources. (In C++, it is sometimes possible to define two things with the same name, but the One-Definition-Rule means the linker is allowed to assume they are both the same thing really and just pick one.)
This is why libraries are supposed to use names that won't be used elsewhere - usually by adding a common prefix to all symbol names (e.g. my_unique_lib_initialize()).
Why not use array of function pointers. Sure you need to initialize it at the start but I think it probably solves what you want to do.
int process1_function(int var);
int process2_function(int var);
int main(void)
{
int i, a = 10;
int (* functions[2])(int);
functions[0] = process1_function;
functions[1] = process2_function;
for(i=0; i < 2; i++)
{
printf("%d", (functions[i])(a));
}
return 0;
}
If you do not need to dynamically change which function you're going to call you can also just prefix the functions:
int process1_function(int var);
int process2_function(int var);
int main(void)
{
printf("%d",process1_function(a));
printf("%d",process2_function(a));
return 0;
}
#include < stdio.h >
int main() {
char *s;
s=call();
printf(s);
}
char* call() {
return("hello");
}
Why these code not working. It's generating an error. How do I make it work?
Two things:
You can't put spaces inside the angle brackets when including a system header (e.g. #include <stdio.h>
You need a prototype for call()
I am trying a global variable to hold my error message in C.
One library called Utils has:
#ifndef private_error_h
#define private_error_h
extern char error[1024];
__declspec(dllexport) void FillError(char* newError);
#define GetErr() error
#endif
File error.c:
#include "private_error.h"
char error[1024];
void FillError(char* newError) {
// ...
}
Then I try to use it in a program:
#include "private_error.h"
int main() {
FillError("General error");
printf("%s\n", GetErr());
return 0;
}
It creates two variables with different addresses. How can I make the program use the variable from the Utils library?
I did manage to bypass this problem by changing GetErr to a function returning the string, but I am still wondering where the error is here.
You have to declare it in your header file as
extern char error[];
and in your code file (.c file) , declare it
char error[1024];
You are allocating it twice
Why not use function like this:
in .h:
char* GetErr();
and in .cpp:
char* GetErr() { return error; }
Try to avoid global variables. In file scope its pretty safe, but if you try to use it trough many files it can cause big errors.