From 409b47172d1499b8ea8d1429b67548cf48044642 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 1 Dec 2023 21:33:18 +0900 Subject: [PATCH] Fix the codes line numbers in prologue and epilogue `C_DECLARATION` includes new line after `"%{"` (prologue) or `"%%"` (epilogue) then adjust `#line` directive and source codes in template. --- spec/fixtures/integration/line_number.l | 45 ++++++++++++++++ spec/fixtures/integration/line_number.y | 68 +++++++++++++++++++++++++ spec/lrama/integration_spec.rb | 13 +++++ template/bison/yacc.c | 2 - 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/integration/line_number.l create mode 100644 spec/fixtures/integration/line_number.y diff --git a/spec/fixtures/integration/line_number.l b/spec/fixtures/integration/line_number.l new file mode 100644 index 00000000..300e31f4 --- /dev/null +++ b/spec/fixtures/integration/line_number.l @@ -0,0 +1,45 @@ +%option noinput nounput noyywrap never-interactive yylineno bison-bridge bison-locations + +%{ + +#include +#include +#include "line_number.h" + +int yycolumn = 0; + +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line = yylineno; \ + yylloc->first_column = yycolumn; \ + yylloc->last_column = yycolumn + yyleng; \ + yycolumn += yyleng; \ + +%} + +NUMBER [0-9]+ + +%% + +{NUMBER} { + yylval->i = atoi(yytext); + return NUM; +} + +[+\-\*\/\(\)] { + return yytext[0]; +} + +[\n|\r\n] {} + +[[:space:]] {} + +<> { + return(YYEOF); +} + +. { + fprintf(stderr, "Illegal character '%s'\n", yytext); + return(YYEOF); +} + +%% diff --git a/spec/fixtures/integration/line_number.y b/spec/fixtures/integration/line_number.y new file mode 100644 index 00000000..182eb468 --- /dev/null +++ b/spec/fixtures/integration/line_number.y @@ -0,0 +1,68 @@ +%{ + +#define YYDEBUG 1 + +#include +#include "line_number.h" +#include "line_number-lexer.h" + +static int yyerror(YYLTYPE *loc, const char *str); +static void line_2(void); + +static void +line_1(void) +{ + printf("line_1: %d\n", __LINE__); +} + +%} + +%union { + int i; +} + +%expect 0 + +%token NUM + +%% + +program : { + printf("line_pre_program: %d\n", __LINE__); + line_1(); + line_2(); + } + expr + { + printf("line_post_program: %d\n", __LINE__); + } + ; + +expr : NUM + ; + +%% + +static int +yyerror(YYLTYPE *loc, const char *str) { + fprintf(stderr, "parse error: %s\\n", str); + return 0; +} + +static void +line_2(void) +{ + printf("line_2: %d\n", __LINE__); +} + +int +main(int argc, char *argv[]) { + yydebug = 1; + + if (argc == 2) { + yy_scan_string(argv[1]); + } + + yyparse(); + return 0; +} diff --git a/spec/lrama/integration_spec.rb b/spec/lrama/integration_spec.rb index f6dab4de..655c9e4e 100644 --- a/spec/lrama/integration_spec.rb +++ b/spec/lrama/integration_spec.rb @@ -107,6 +107,19 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: []) end end + describe "__LINE__ of each place" do + it "prints line number of each place" do + expected = <<~STR + line_pre_program: 31 + line_1: 15 + line_2: 55 + line_post_program: 37 + STR + + test_parser("line_number", "1 + 2", expected) + end + end + # TODO: Add test case for "(1+2" describe "error_recovery" do it "returns 101 for '(1+)'" do diff --git a/template/bison/yacc.c b/template/bison/yacc.c index 0e17b46f..f72d3461 100644 --- a/template/bison/yacc.c +++ b/template/bison/yacc.c @@ -72,7 +72,6 @@ <%- if output.aux.prologue -%> /* First part of user prologue. */ #line <%= output.aux.prologue_first_lineno %> "<%= output.grammar_file_path %>" - <%= output.aux.prologue %> #line [@oline@] [@ofile@] <%- end -%> @@ -2048,7 +2047,6 @@ YYLTYPE yylloc = yyloc_default; <%# b4_percent_code_get([[epilogue]]) -%> <%- if output.aux.epilogue -%> #line <%= output.aux.epilogue_first_lineno - 1 %> "<%= output.grammar_file_path %>" - <%= output.aux.epilogue -%> <%- end -%>