Skip to content

Commit

Permalink
Ensure compatibility with Bison for --locations option
Browse files Browse the repository at this point in the history
```
❯ bison -h
Usage: bison [OPTION]... FILE
Generate a deterministic LR or generalized LR (GLR) parser employing
: (snip)
Tuning the Parser:
  -L, --language=LANGUAGE          specify the output programming language
  -S, --skeleton=FILE              specify the skeleton to use
  -t, --debug                      instrument the parser for tracing
                                   same as '-Dparse.trace'
      --locations                  enable location support
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
  • Loading branch information
ydah committed Feb 14, 2025
1 parent f2be27f commit e4a8a87
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 13 deletions.
6 changes: 4 additions & 2 deletions lib/lrama/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def read_input

def build_grammar(text)
grammar =
Lrama::Parser.new(text, @options.grammar_file, @options.debug, @options.define).parse
Lrama::Parser.new(text, @options.grammar_file, @options.debug, @options.locations, @options.define).parse
merge_stdlib(grammar)
prepare_grammar(grammar)
grammar
Expand All @@ -68,7 +68,9 @@ def merge_stdlib(grammar)
stdlib_grammar = Lrama::Parser.new(
stdlib_text,
STDLIB_FILE_PATH,
@options.debug
@options.debug,
@options.locations,
@options.define,
).parse

grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
Expand Down
4 changes: 2 additions & 2 deletions lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Grammar
:find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
:fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!

def initialize(rule_counter, define = {})
def initialize(rule_counter, locations, define = {})
@rule_counter = rule_counter

# Code defined by "%code"
Expand All @@ -56,7 +56,7 @@ def initialize(rule_counter, define = {})
@accept_symbol = nil
@aux = Auxiliary.new
@no_stdlib = false
@locations = false
@locations = locations
@define = define

append_special_symbols
Expand Down
1 change: 1 addition & 0 deletions lib/lrama/option_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def parse_by_option_parser(argv)
o.on('-S', '--skeleton=FILE', 'specify the skeleton to use') {|v| @options.skeleton = v }
o.on('-t', '--debug', 'display debugging outputs of internal parser') {|v| @options.debug = true }
o.separator " same as '-Dparse.trace'"
o.on('--locations', 'enable location support') {|v| @options.locations = true }
o.on('-D', '--define=NAME[=VALUE]', Array, "similar to '%define NAME VALUE'") do |v|
@options.define = v.each_with_object({}) do |item, hash|
key, value = item.split('=', 2)
Expand Down
2 changes: 2 additions & 0 deletions lib/lrama/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Lrama
# Command line options.
class Options
attr_accessor :skeleton #: String
attr_accessor :locations #: bool
attr_accessor :header #: bool
attr_accessor :header_file #: String?
attr_accessor :report_file #: String?
Expand All @@ -24,6 +25,7 @@ class Options
# @rbs () -> void
def initialize
@skeleton = "bison/yacc.c"
@locations = false
@define = {}
@header = false
@header_file = nil
Expand Down
5 changes: 3 additions & 2 deletions lib/lrama/parser.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -428,18 +428,19 @@ end

include Lrama::Tracer::Duration

def initialize(text, path, debug = false, define = {})
def initialize(text, path, debug = false, locations = false, define = {})
@grammar_file = Lrama::Lexer::GrammarFile.new(path, text)
@yydebug = debug || define.key?('parse.trace')
@rule_counter = Lrama::Grammar::Counter.new(0)
@midrule_action_counter = Lrama::Grammar::Counter.new(1)
@locations = locations
@define = define
end

def parse
report_duration(:parse) do
@lexer = Lrama::Lexer.new(@grammar_file)
@grammar = Lrama::Grammar.new(@rule_counter, @define)
@grammar = Lrama::Grammar.new(@rule_counter, @locations, @define)
@precedence_number = 0
reset_precs
do_parse
Expand Down
2 changes: 2 additions & 0 deletions sig/generated/lrama/options.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module Lrama
class Options
attr_accessor skeleton: String

attr_accessor locations: bool

attr_accessor header: bool

attr_accessor header_file: String?
Expand Down
2 changes: 1 addition & 1 deletion sig/lrama/grammar.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module Lrama
attr_accessor sym_to_rules: Hash[Integer, Array[Rule]]
attr_accessor no_stdlib: bool

def initialize: (Counter rule_counter) -> void
def initialize: (Counter rule_counter, bool locations) -> void
def create_rule_builder: (Counter rule_counter, Counter midrule_action_counter) -> RuleBuilder
def add_percent_code: (id: Lexer::Token, code: Lexer::Token::UserCode) -> Array[PercentCode]
def add_destructor: (ident_or_tags: Array[Lexer::Token::Ident|Lexer::Token::Tag], token_code: Code, lineno: Integer) -> Array[Destructor]
Expand Down
1 change: 1 addition & 0 deletions spec/lrama/option_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
-S, --skeleton=FILE specify the skeleton to use
-t, --debug display debugging outputs of internal parser
same as '-Dparse.trace'
--locations enable location support
-D, --define=NAME[=VALUE] similar to '%define NAME VALUE'
Output:
Expand Down
24 changes: 20 additions & 4 deletions spec/lrama/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@
context 'with define is specified' do
context 'with `api.pure`' do
it '@yydebug is true' do
parser = Lrama::Parser.new("", "", true, {'api.pure' => nil})
parser = Lrama::Parser.new("", "", true, false, {'api.pure' => nil})
yydebug = parser.instance_variable_get(:@yydebug)
expect(yydebug).to be_truthy
end
end

context 'with `parse.trace`' do
it '@yydebug is true' do
parser = Lrama::Parser.new("", "", true, {'parse.trace' => nil})
parser = Lrama::Parser.new("", "", true, false, {'parse.trace' => nil})
yydebug = parser.instance_variable_get(:@yydebug)
expect(yydebug).to be_truthy
end
Expand All @@ -83,21 +83,37 @@
context 'with define is specified' do
context 'with `api.pure`' do
it '@yydebug is false' do
parser = Lrama::Parser.new("", "", false, {'api.pure' => nil})
parser = Lrama::Parser.new("", "", false, false, {'api.pure' => nil})
yydebug = parser.instance_variable_get(:@yydebug)
expect(yydebug).to be_falsey
end
end

context 'with `parse.trace`' do
it '@yydebug is true' do
parser = Lrama::Parser.new("", "", false, {'parse.trace' => nil})
parser = Lrama::Parser.new("", "", false, false, {'parse.trace' => nil})
yydebug = parser.instance_variable_get(:@yydebug)
expect(yydebug).to be_truthy
end
end
end
end

context 'when locations is true' do
it '@locations is true' do
parser = Lrama::Parser.new("", "", false, true)
locations = parser.instance_variable_get(:@locations)
expect(locations).to be_truthy
end
end

context 'when locations is false' do
it '@locations is false' do
parser = Lrama::Parser.new("", "", false, false)
locations = parser.instance_variable_get(:@locations)
expect(locations).to be_falsey
end
end
end

describe '#parse' do
Expand Down

0 comments on commit e4a8a87

Please # to comment.