Skip to content

Commit

Permalink
Merge pull request #446 from ydah/locations
Browse files Browse the repository at this point in the history
Ensure compatibility with Bison for `%locations`
  • Loading branch information
ydah authored Jun 18, 2024
2 parents 85efe0e + 1595f38 commit caa982c
Show file tree
Hide file tree
Showing 25 changed files with 657 additions and 525 deletions.
14 changes: 8 additions & 6 deletions lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ class Grammar
extend Forwardable

attr_reader :percent_codes, :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux
attr_accessor :union, :expect,
:printers, :error_tokens,
:lex_param, :parse_param, :initial_action,
attr_accessor :union, :expect, :printers, :error_tokens, :lex_param, :parse_param, :initial_action,
:after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
:symbols_resolver, :types,
:rules, :rule_builders,
:sym_to_rules, :no_stdlib
:symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations

def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
Expand Down Expand Up @@ -60,6 +56,7 @@ def initialize(rule_counter)
@accept_symbol = nil
@aux = Auxiliary.new
@no_stdlib = false
@locations = false

append_special_symbols
end
Expand Down Expand Up @@ -155,6 +152,7 @@ def prepare
fill_sym_to_rules
compute_nullable
compute_first_set
set_locations
end

# TODO: More validation methods
Expand Down Expand Up @@ -396,5 +394,9 @@ def validate_rule_lhs_is_nterm!

raise errors.join("\n")
end

def set_locations
@locations = @locations || @rules.any? {|rule| rule.contains_at_reference? }
end
end
end
6 changes: 6 additions & 0 deletions lib/lrama/grammar/rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ def translated_code

Code::RuleAction.new(type: :rule_action, token_code: token_code, rule: self).translated_code
end

def contains_at_reference?
return false unless token_code

token_code.references.any? {|r| r.type == :at }
end
end
end
end
1 change: 1 addition & 0 deletions lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Lexer
%rule
%no-stdlib
%inline
%locations
)

def initialize(grammar_file)
Expand Down
3 changes: 2 additions & 1 deletion lib/lrama/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ def parse_param_use(val, loc)

# b4_yylex_formals
def yylex_formals
ary = ["&yylval", "&yylloc"]
ary = ["&yylval"]
ary << "&yylloc" if @grammar.locations

if @grammar.lex_param
ary << lex_param_name
Expand Down
1,026 changes: 518 additions & 508 deletions lib/lrama/parser.rb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ rule
@grammar.initial_action = Grammar::Code::InitialActionCode.new(type: :initial_action, token_code: val[3])
}
| "%no-stdlib" { @grammar.no_stdlib = true }
| "%locations" { @grammar.locations = true }

grammar_declaration: "%union" "{"
{
Expand Down
2 changes: 2 additions & 0 deletions sample/calc.y
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%left '+' '-'
%left '*' '/'

%locations

%rule %inline op : '+' { + }
| '-' { - }
| '*' { * }
Expand Down
4 changes: 2 additions & 2 deletions sample/parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

%code provides {

static enum yytokentype yylex(YYSTYPE *lval, YYLTYPE *yylloc);
static enum yytokentype yylex(YYSTYPE *lval);
static void yyerror(YYLTYPE *yylloc, const char *msg);

}
Expand Down Expand Up @@ -44,7 +44,7 @@ factor : number
// Epilogue

static enum yytokentype
yylex(YYSTYPE *lval, YYLTYPE *yylloc)
yylex(YYSTYPE *lval)
{
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions sig/lrama/grammar.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Lrama
@accept_symbol: Grammar::Symbol
@aux: Auxiliary
@no_stdlib: bool
@locations: bool
@union: Union

extend Forwardable
Expand Down Expand Up @@ -89,5 +90,6 @@ module Lrama
def fill_symbols: () -> Array[Grammar::Symbol]
def fill_sym_to_rules: () -> Array[Rule]
def validate_rule_lhs_is_nterm!: () -> void
def set_locations: () -> void
end
end
2 changes: 2 additions & 0 deletions sig/lrama/grammar/rule.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ module Lrama
def initial_rule?: -> bool

def with_actions: -> String

def contains_at_reference?: -> bool
end
end
end
2 changes: 2 additions & 0 deletions spec/fixtures/integration/after_shift.y
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ after_pop_stack(int len)
%left '+' '-'
%left '*' '/'

%locations

%%

program : /* empty */
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/calculator.y
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%left '+' '-'
%left '*' '/'

%locations

%%

program : /* empty */
Expand Down
40 changes: 40 additions & 0 deletions spec/fixtures/integration/contains_at_reference.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
%option noinput nounput noyywrap never-interactive yylineno bison-bridge bison-locations

%{

#include <stdio.h>
#include <stdlib.h>
#include "prologue_epilogue_optional.h"

%}

NUMBER [0-9]+

%%

{NUMBER} {
((void) yylloc);
yylval->val = atoi(yytext);
return 1;
}

[+\-\*\/\(\)] {
return yytext[0];
}

[\n|\r\n] {
return(YYEOF);
}

[[:space:]] {}

<<EOF>> {
return(YYEOF);
}

. {
fprintf(stderr, "Illegal character '%s'\n", yytext);
return(YYEOF);
}

%%
37 changes: 37 additions & 0 deletions spec/fixtures/integration/contains_at_reference.y
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
%{

#include <stdio.h>
#include "contains_at_reference.h"
#include "contains_at_reference-lexer.h"

static int yyerror(YYLTYPE *loc, const char *str);

%}

%union {
int val;
}

%%

program : /* empty */ { (void)@1; }
;

%%

static int yyerror(YYLTYPE *loc, const char *str) {
fprintf(stderr, "parse error: %s\n", str);
return 0;
}

int main(int argc, char *argv[]) {
if (argc == 2) {
yy_scan_string(argv[1]);
}

if (yyparse()) {
fprintf(stderr, "syntax error\n");
return 1;
}
return 0;
}
2 changes: 2 additions & 0 deletions spec/fixtures/integration/destructors.y
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%left '+' '-'
%left '*' '/'

%locations

%destructor {
printf("destructor for val1: %d\n", $$);
printf("line for val1: %d\n", __LINE__);
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/error_recovery.y
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%left '+' '-'
%left '*' '/'

%locations

%error-token {
$$ = 100;
} NUM
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/line_number.y
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ line_1(void)

%token <i> NUM

%locations

%%

program : {
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/named_references.y
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%token <val> NUM
%type <val> expr

%locations

%%

line: expr
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/parameterizing_rules.y
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%type <num> stmt
%type <str> opt_nl

%locations

%%

program: stmts
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/params.y
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static int yyerror(YYLTYPE *loc, int parse_param, const char *str);
%left '+' '-'
%left '*' '/'

%locations

%%

program : /* empty */
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/printers.y
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
printf("expr: %d\n", $$);
} expr // printer for symbol

%locations

%%

program : /* empty */
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/prologue_epilogue_optional.y
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
int val;
}

%locations

%%

program : /* empty */
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/typed_midrule_actions.y
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
%token <val> NUM
%type <val> expr

%locations

%%

line: expr
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/integration/user_defined_parameterizing_rules.y
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ static int yyerror(YYLTYPE *loc, const char *str);
}
;

%locations

%%

program: stmts
Expand Down
20 changes: 12 additions & 8 deletions spec/lrama/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: [])
test_parser("prologue_epilogue_optional", "", "")
end

it "contains at reference in action" do
test_parser("contains_at_reference", "", "")
end

describe "YYDEBUG, %lex-param, %parse-param option are enabled" do
it "returns 9 for '(1+2)*3'" do
test_parser("params", "(1+2)*3", "=> 9")
Expand Down Expand Up @@ -147,28 +151,28 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: [])
it "prints messages when symbol is discarded" do
expected = <<~STR
destructor for expr: 1
line for expr: 43
line for expr: 45
STR
test_parser("destructors", "1 +", expected, expect_success: false)

expected = <<~STR
destructor for val2: 1
line for val2: 33
line for val2: 35
STR
test_parser("destructors", "+ 1 -", expected, expect_success: false)

expected = <<~STR
=> 3
destructor for val1: 3
line for val1: 28
line for val1: 30
STR
test_parser("destructors", "1 + 2 3", expected, expect_success: false)

expected = <<~STR
destructor for val4: 10
line for val4: 38
line for val4: 40
destructor for expr: 1
line for expr: 43
line for expr: 45
STR
test_parser("destructors", "1 * ", expected, expect_success: false)
end
Expand All @@ -177,10 +181,10 @@ def generate_object(grammar_file_path, c_path, obj_path, command_args: [])
describe "__LINE__ of each place" do
it "prints line number of each place" do
expected = <<~STR
line_pre_program: 31
line_pre_program: 33
line_1: 15
line_2: 55
line_post_program: 37
line_2: 57
line_post_program: 39
STR

test_parser("line_number", "1 + 2", expected)
Expand Down

0 comments on commit caa982c

Please sign in to comment.