So I am currently trying to write a fairly simple program that takes a file as input, reads it, and lexes it (lexical analysis) (I will get to parsing and interpreting later)
I have written similar programs before that worked perfectly, but surprisingly, this one hangs when I add a function at the end.
The following works perfectly:
#include <stdio.h>
#include <stdlib.h>
#include "include/slex.h"
int main(void) {
// Read the file and save it into source.
printf("start\n");
FILE* fp = fopen("test.sl", "r");
printf("fileopen\n");
fseek(fp, 0, SEEK_END);
printf("seek\n");
char* source = malloc((ftell(fp) 1) * sizeof (char)); // 1 because of the null terminator.
printf("allocation\n");
fseek(fp, 0, SEEK_SET);
char c;
int i = 0;
while ((c = fgetc(fp)) != EOF) {
source[i ] = c;
} // Iterate through every single character in the file and store it into source.
source[i] = '\0';
fclose(fp);
// Now lex the file;
printf("Lex\n");
lexer_t lexer;
printf("lex2\n");
lexer_init(&lexer, source);
printf("lex3\n");
/*
lex(&lexer);
printf("lex4");
tl_print(&lexer.tokens);
*/
}
But when I uncomment (hope that is an actual word) lex(&lexer)
, it just hangs. It does not print the previous statements.
The function lex
is defined in slex.c and slex.c includes slex.h.
I compiled it with gcc -Wall Wextra -o sl main.c slex.c
, and it does not give me any warning, nor any error.
void lex(lexer_t* lexer):
void lex(lexer_t* lexer) {
printf("lex"); // Debugging
// Some people would call this function "make_tokens", I will call it "lex".
while (lexer->current != '\0') {
if (lexer->current == '\n') {
token_t token = {.type = NEWLINE};
tl_append(&lexer->tokens, token);
}
if (isdigit(lexer->current)) {
token_t token = {.type = INT, .int_value = lex_integer(lexer)};
tl_append(&lexer->tokens, token);
}
else if (isalpha(lexer->current)) {
token_t token = {.type = ID, .id_value = lex_identifier(lexer)};
tl_append(&lexer->tokens, token);
}
}
}
I hope someone finds a solution to my problem, because I do not understand it. Have a nice day and thank you.
And do not hesitate to ask if you need more information, just comment it and I will edit my question.
CodePudding user response:
As Bill Lynch said, Adding fflush(stdout);
before lex(&lexer);
solved my issue. Thanks to everyone who came by this question, really appreciate your help. I wish you all a nice day.
CodePudding user response:
Credit @Bill Lynch (first comment) who noted "app will [likely] hang" with infinite loop.
It's one thing to printf()
to confirm operation. It's something else to check return codes and exit with helpful message.
Below is a rewritten (untested) version of your code using short name aliases to enhance clarity of what is being performed at different locations.
#include <stdio.h>
#include <stdlib.h>
#include "include/slex.h"
void lex( lexer_t *l ) {
fprintf( stderr, "Entered lex()\n" ); // debug
char c;
while( ( c = l->current ) != '\0' ) {
token_t t = { 0 };
if( c == '\n') t.type = NEWLINE;
// still infinite loop...
// what "advances" the pointer?? Credit @Craig Estey
else if( isdigit( c ) ) t.type = INT, t.int_value = lex_integer( l );
else if( isalpha( c) ) t.type = ID, t.id_value = lex_identifier( l );
else { // equivalent to "default:" in a "switch"
fprintf( stderr, "Un-lex-able char ('%c') encountered\n", c );
exit( EXIT_FAILURE );
}
tl_append( &l->tokens, t );
}
}
int main() {
char *fname = "test.sl";
FILE* fp = fopen( fname, "r" );
if( fp == NULL ) {
fprintf( stderr, "Failed to open %s\n", fname );
exit( EXIT_FAILURE );
}
fseek( fp, 0, SEEK_END );
size_t size = ftell( fp );
fseek(fp, 0, SEEK_SET);
fprintf( stderr, "Size %zu\n", size ); // debug
char *buf = malloc( (size 1) * sizeof *buf ); // 1 because of the null terminator.
if( buf == NULL ) {
fprintf( stderr, "Failed to alloc block %zu\n", size 1 );
exit( EXIT_FAILURE );
}
size_t nread = fread( buf, sizeof buf[0], size, fp );
if( nread != size ) {
fprintf( stderr, "Expected %zu. Read %zu\n", size. nread );
exit( EXIT_FAILURE );
}
fclose( fp );
buf[ nread ] = '\0';
lexer_t lexer;
lexer_init( &lexer, buf );
lex( &lexer );
// free( buf ); // Unsure if you refer back to original..
tl_print( &lexer.tokens );
return 0;
}
You can add as many optimistic "making progress" printf calls as you'd like. It's the pessimistic "not working" print statements that are needed to push forward.