Skip to content

Commit 13686ec

Browse files
authored
Merge pull request #28 from LangProc/dev
Added better error messages in Flex with yylineno + some minor visual fixes
2 parents 8b8ee31 + 5bca02f commit 13686ec

File tree

5 files changed

+67
-36
lines changed

5 files changed

+67
-36
lines changed

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ DEPENDENCIES := $(patsubst src/%.cpp,build/%.d,$(SOURCES))
1818
OBJECTS := $(patsubst src/%.cpp,build/%.o,$(SOURCES))
1919
OBJECTS += build/parser.tab.o build/lexer.yy.o
2020

21-
.PHONY: default clean coverage
21+
.PHONY: default clean coverage remove_old_gcda
2222

23-
default: bin/c_compiler
23+
default: remove_old_gcda bin/c_compiler
2424

2525
bin/c_compiler: $(OBJECTS)
2626
@mkdir -p bin
@@ -47,6 +47,9 @@ coverage:
4747
genhtml coverage/cov.info -o coverage
4848
@find . -name "*.gcda" -delete
4949

50+
remove_old_gcda:
51+
@find . -name "*.gcda" -delete
52+
5053
clean :
5154
@rm -rf coverage/
5255
@rm -rf build/

src/compiler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ int main(int argc, char **argv)
4242

4343
NodePtr Parse(const std::string& compile_source_path)
4444
{
45-
std::cout << "Parsing ..." << compile_source_path << std::endl;
45+
std::cout << "Parsing " << compile_source_path << "..." << std::endl;
4646

4747
NodePtr root = ParseAST(compile_source_path);
4848

src/lexer.flex

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
%option noyywrap
2+
%option yylineno
23

34
%{
45
// A lot of this lexer is based off the ANSI C grammar:
5-
// https://www.lysator.liu.se/c/ANSI-C-grammar-l.html#MUL-ASSIGN
6-
// Avoid error "error: `fileno' was not declared in this scope"
6+
// https://www.lysator.liu.se/c/ANSI-C-grammar-l.html
7+
8+
// Avoids error "error: `fileno' was not declared in this scope"
79
extern "C" int fileno(FILE *stream);
810

911
#include "parser.tab.hpp"
1012

1113
// Suppress warning about unused function
12-
[[maybe_unused]] static void yyunput (int c, char * yy_bp );
14+
[[maybe_unused]] static void yyunput (int c, char * yy_bp);
1315
%}
1416

1517
D [0-9]
@@ -116,12 +118,6 @@ L?\"(\\.|[^\\"])*\" {/* TODO process string literal */; return(STRING_LITERAL);}
116118
"?" {return('?');}
117119
118120
[ \a\b\t\v\f\n\r] {/* ignore new lines and special sequences */}
119-
. {/* ignore bad characters */}
121+
. {std::cerr << "Unknown token: " << yytext << std::endl; return(UNKNOWN);}
120122
121123
%%
122-
123-
void yyerror (char const *s)
124-
{
125-
fprintf(stderr, "Lexing error: %s\n", s);
126-
exit(1);
127-
}

src/parser.y

+29-13
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,26 @@
44
// rename parser_full.y to parser.y once you're happy with
55
// how this example works.
66

7-
%code requires{
8-
#include "ast.hpp"
9-
7+
%code requires {
8+
#include "ast.hpp"
109
using namespace ast;
1110

12-
extern Node* g_root;
13-
extern FILE* yyin;
14-
int yylex(void);
15-
void yyerror(const char*);
11+
extern int yylineno;
12+
extern char* yytext;
13+
extern Node* g_root;
14+
extern FILE* yyin;
15+
16+
int yylex(void);
17+
void yyerror(const char*);
1618
int yylex_destroy(void);
1719
}
1820

19-
%union{
20-
Node* node;
21-
NodeList* node_list;
21+
%define parse.error detailed
22+
%define parse.lac full
23+
24+
%union {
25+
Node* node;
26+
NodeList* node_list;
2227
int number_int;
2328
double number_float;
2429
std::string* string;
@@ -33,6 +38,7 @@
3338
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
3439
%token STRUCT UNION ENUM ELLIPSIS
3540
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
41+
%token UNKNOWN
3642

3743
%type <node> translation_unit external_declaration function_definition primary_expression postfix_expression
3844
%type <node> unary_expression cast_expression multiplicative_expression additive_expression shift_expression relational_expression
@@ -51,7 +57,7 @@
5157
%%
5258

5359
ROOT
54-
: translation_unit { g_root = $1; }
60+
: translation_unit { g_root = $1; }
5561

5662
translation_unit
5763
: external_declaration { $$ = $1; }
@@ -185,18 +191,28 @@ expression
185191

186192
%%
187193

194+
void yyerror (const char *s)
195+
{
196+
std::cerr << "Error: " << s << " at line " << yylineno;
197+
std::cerr << " near '" << yytext << "'" << std::endl;
198+
std::exit(1);
199+
}
200+
188201
Node* g_root;
189202

190203
NodePtr ParseAST(std::string file_name)
191204
{
192205
yyin = fopen(file_name.c_str(), "r");
193-
if(yyin == NULL){
206+
if (yyin == nullptr) {
194207
std::cerr << "Couldn't open input file: " << file_name << std::endl;
195-
exit(1);
208+
std::exit(1);
196209
}
210+
197211
g_root = nullptr;
198212
yyparse();
213+
199214
fclose(yyin);
200215
yylex_destroy();
216+
201217
return NodePtr(g_root);
202218
}

src/parser_full.y.example

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
// Adapted from: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
22

3-
%code requires{
4-
#include "ast.hpp"
5-
3+
%code requires {
4+
#include "ast.hpp"
65
using namespace ast;
76

8-
extern Node* g_root;
9-
extern FILE* yyin;
10-
int yylex(void);
11-
void yyerror(const char*);
7+
extern int yylineno;
8+
extern char* yytext;
9+
extern Node* g_root;
10+
extern FILE* yyin;
11+
12+
int yylex(void);
13+
void yyerror(const char*);
1214
int yylex_destroy(void);
1315
}
1416

17+
%define parse.error detailed
18+
%define parse.lac full
19+
1520
// Represents the value associated with any kind of AST node.
16-
%union{
21+
%union {
1722
Node* node;
1823
NodeList* node_list;
1924
int number_int;
@@ -30,6 +35,7 @@
3035
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
3136
%token STRUCT UNION ENUM ELLIPSIS
3237
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
38+
%token UNKNOWN
3339

3440
%type <node> translation_unit external_declaration function_definition primary_expression postfix_expression argument_expression_list
3541
%type <node> unary_expression cast_expression multiplicative_expression additive_expression shift_expression relational_expression
@@ -462,18 +468,28 @@ jump_statement
462468

463469
%%
464470

471+
void yyerror (const char *s)
472+
{
473+
std::cerr << "Error: " << s << " at line " << yylineno;
474+
std::cerr << " near '" << yytext << "'" << std::endl;
475+
std::exit(1);
476+
}
477+
465478
Node* g_root;
466479

467480
NodePtr ParseAST(std::string file_name)
468481
{
469482
yyin = fopen(file_name.c_str(), "r");
470-
if(yyin == NULL){
483+
if (yyin == nullptr) {
471484
std::cerr << "Couldn't open input file: " << file_name << std::endl;
472-
exit(1);
485+
std::exit(1);
473486
}
487+
474488
g_root = nullptr;
475489
yyparse();
490+
476491
fclose(yyin);
477492
yylex_destroy();
493+
478494
return NodePtr(g_root);
479495
}

0 commit comments

Comments
 (0)