Skip to content

Commit

Permalink
Support Named References for location
Browse files Browse the repository at this point in the history
  • Loading branch information
yui-knk committed Sep 8, 2023
1 parent 7ded310 commit 08ea85a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 4 deletions.
2 changes: 2 additions & 0 deletions lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ def lex_user_code(ss, line, column, lines)
references << [:at, "$", nil, str.length, str.length + ss[0].length - 1]
when ss.scan(/@(\d+)/) # @1
references << [:at, Integer(ss[1]), nil, str.length, str.length + ss[0].length - 1]
when ss.scan(/@([a-zA-Z_.][-a-zA-Z0-9_.]*)/) # @foo, @expr
references << [:at, ss[1], nil, str.length, str.length + ss[0].length - 1]
when ss.scan(/{/)
brace_count += 1
when ss.scan(/}/)
Expand Down
92 changes: 88 additions & 4 deletions spec/lrama/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,46 @@ def test_rules(rules, input, expected, command_args: [], debug: false)
%w[NUM val 2],
%w['+'],
]
cases = generate_lexer_body(input)

test_grammar(<<~Grammar, "expr[left]: 0.0-0.1. expr[right]: 1.0-1.1. line: 0.0-2.1. => 3")
%{
#include <stdio.h>
#include "test.h"
typedef struct code_location {
int first_line;
int first_column;
int last_line;
int last_column;
} code_location_t;
#define YYLTYPE code_location_t
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
if (N) \
{ \
(Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC(Rhs, N).last_line; \
(Current).last_column = YYRHSLOC(Rhs, N).last_column; \
} \
else \
{ \
(Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
(Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
(Current).last_line = YYRHSLOC(Rhs, 0).last_line; \
(Current).last_column = YYRHSLOC(Rhs, 0).last_column; \
} \
while (0)
static int yylex(YYSTYPE *val, YYLTYPE *loc);
static void print_location(YYLTYPE *loc);
static int yyerror(YYLTYPE *loc, const char *str);
%}
test_rules(<<~Rules, input, "=> 3")
%union {
int val;
}
Expand All @@ -223,16 +261,62 @@ def test_rules(rules, input, expected, command_args: [], debug: false)
%%
line: expr
{ (void)yynerrs; printf("=> %d", $expr); }
{
(void)yynerrs;
printf("line: ");
print_location(&@expr);
printf("=> %d", $expr);
}
;
expr[result]: NUM
| expr[left] expr[right] '+'
{ $result = $left + $right; }
{
printf("expr[left]: ");
print_location(&@left);
printf("expr[right]: ");
print_location(&@right);
$result = $left + $right;
}
;
%%
Rules
int c = 0;
static int yylex(YYSTYPE *yylval, YYLTYPE *loc) {
loc->first_line = c;
loc->first_column = 0;
loc->last_line = c;
loc->last_column = 1;
switch (c++) {
#{cases}
default:
// End of Input
return -1;
}
}
static void print_location(YYLTYPE *loc) {
printf("%d.%d-%d.%d. ", loc->first_line, loc->first_column, loc->last_line, loc->last_column);
}
static int yyerror(YYLTYPE *loc, const char *str) {
fprintf(stderr, "parse error: %s\\n", str);
return 0;
}
int main() {
yyparse();
return 0;
}
Grammar
end
end

Expand Down

0 comments on commit 08ea85a

Please sign in to comment.