Skip to content

Commit fc19ce0

Browse files
committed
Lrama v0.7.1
1 parent 44693ee commit fc19ce0

File tree

115 files changed

+5663
-2417
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+5663
-2417
lines changed

tool/lrama/NEWS.md

Lines changed: 370 additions & 35 deletions
Large diffs are not rendered by default.

tool/lrama/exe/lrama

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
$LOAD_PATH << File.join(__dir__, "../lib")
55
require "lrama"
66

7-
Lrama::Command.new.run(ARGV.dup)
7+
Lrama::Command.new(ARGV.dup).run

tool/lrama/lib/lrama.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
require_relative "lrama/command"
55
require_relative "lrama/context"
66
require_relative "lrama/counterexamples"
7-
require_relative "lrama/diagnostics"
7+
require_relative "lrama/diagram"
88
require_relative "lrama/digraph"
9+
require_relative "lrama/erb"
910
require_relative "lrama/grammar"
10-
require_relative "lrama/grammar_validator"
1111
require_relative "lrama/lexer"
1212
require_relative "lrama/logger"
1313
require_relative "lrama/option_parser"
1414
require_relative "lrama/options"
1515
require_relative "lrama/output"
1616
require_relative "lrama/parser"
17-
require_relative "lrama/report"
17+
require_relative "lrama/reporter"
1818
require_relative "lrama/state"
1919
require_relative "lrama/states"
20-
require_relative "lrama/states_reporter"
21-
require_relative "lrama/trace_reporter"
20+
require_relative "lrama/tracer"
2221
require_relative "lrama/version"
22+
require_relative "lrama/warnings"

tool/lrama/lib/lrama/bitmap.rb

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
module Lrama
55
module Bitmap
6-
# @rbs (Array[Integer] ary) -> Integer
6+
# @rbs!
7+
# type bitmap = Integer
8+
9+
# @rbs (Array[Integer] ary) -> bitmap
710
def self.from_array(ary)
811
bit = 0
912

@@ -14,21 +17,31 @@ def self.from_array(ary)
1417
bit
1518
end
1619

17-
# @rbs (Integer int) -> Array[Integer]
20+
# @rbs (Integer int) -> bitmap
21+
def self.from_integer(int)
22+
1 << int
23+
end
24+
25+
# @rbs (bitmap int) -> Array[Integer]
1826
def self.to_array(int)
1927
a = [] #: Array[Integer]
2028
i = 0
2129

22-
while int > 0 do
23-
if int & 1 == 1
30+
len = int.bit_length
31+
while i < len do
32+
if int[i] == 1
2433
a << i
2534
end
2635

2736
i += 1
28-
int >>= 1
2937
end
3038

3139
a
3240
end
41+
42+
# @rbs (bitmap int, Integer size) -> Array[bool]
43+
def self.to_bool_array(int, size)
44+
Array.new(size) { |i| int[i] == 1 }
45+
end
3346
end
3447
end

tool/lrama/lib/lrama/command.rb

Lines changed: 95 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,64 +5,116 @@ class Command
55
LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__)))
66
STDLIB_FILE_PATH = File.join(LRAMA_LIB, 'grammar', 'stdlib.y')
77

8-
def run(argv)
9-
begin
10-
options = OptionParser.new.parse(argv)
11-
rescue => e
12-
message = e.message
13-
message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
14-
abort message
15-
end
16-
17-
Report::Duration.enable if options.trace_opts[:time]
8+
def initialize(argv)
9+
@logger = Lrama::Logger.new
10+
@options = OptionParser.parse(argv)
11+
@tracer = Tracer.new(STDERR, **@options.trace_opts)
12+
@reporter = Reporter.new(**@options.report_opts)
13+
@warnings = Warnings.new(@logger, @options.warnings)
14+
rescue => e
15+
abort format_error_message(e.message)
16+
end
1817

19-
text = options.y.read
20-
options.y.close if options.y != STDIN
21-
begin
22-
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug, options.define).parse
23-
unless grammar.no_stdlib
24-
stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
25-
grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
18+
def run
19+
Lrama::Reporter::Profile::CallStack.report(@options.profile_opts[:call_stack]) do
20+
Lrama::Reporter::Profile::Memory.report(@options.profile_opts[:memory]) do
21+
execute_command_workflow
2622
end
27-
grammar.prepare
28-
grammar.validate!
29-
rescue => e
30-
raise e if options.debug
31-
message = e.message
32-
message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
33-
abort message
3423
end
35-
states = Lrama::States.new(grammar, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
24+
end
25+
26+
private
27+
28+
def execute_command_workflow
29+
@tracer.enable_duration
30+
text = read_input
31+
grammar = build_grammar(text)
32+
states, context = compute_status(grammar)
33+
render_reports(states) if @options.report_file
34+
@tracer.trace(grammar)
35+
render_diagram(grammar)
36+
render_output(context, grammar)
37+
states.validate!(@logger)
38+
@warnings.warn(grammar, states)
39+
end
40+
41+
def read_input
42+
text = @options.y.read
43+
@options.y.close unless @options.y == STDIN
44+
text
45+
end
46+
47+
def build_grammar(text)
48+
grammar =
49+
Lrama::Parser.new(text, @options.grammar_file, @options.debug, @options.locations, @options.define).parse
50+
merge_stdlib(grammar)
51+
prepare_grammar(grammar)
52+
grammar
53+
rescue => e
54+
raise e if @options.debug
55+
abort format_error_message(e.message)
56+
end
57+
58+
def format_error_message(message)
59+
return message unless Exception.to_tty?
60+
61+
message.gsub(/.+/, "\e[1m\\&\e[m")
62+
end
63+
64+
def merge_stdlib(grammar)
65+
return if grammar.no_stdlib
66+
67+
stdlib_text = File.read(STDLIB_FILE_PATH)
68+
stdlib_grammar = Lrama::Parser.new(
69+
stdlib_text,
70+
STDLIB_FILE_PATH,
71+
@options.debug,
72+
@options.locations,
73+
@options.define,
74+
).parse
75+
76+
grammar.prepend_parameterized_rules(stdlib_grammar.parameterized_rules)
77+
end
78+
79+
def prepare_grammar(grammar)
80+
grammar.prepare
81+
grammar.validate!
82+
end
83+
84+
def compute_status(grammar)
85+
states = Lrama::States.new(grammar, @tracer)
3686
states.compute
3787
states.compute_ielr if grammar.ielr_defined?
38-
context = Lrama::Context.new(states)
88+
[states, Lrama::Context.new(states)]
89+
end
3990

40-
if options.report_file
41-
reporter = Lrama::StatesReporter.new(states)
42-
File.open(options.report_file, "w+") do |f|
43-
reporter.report(f, **options.report_opts)
44-
end
91+
def render_reports(states)
92+
File.open(@options.report_file, "w+") do |f|
93+
@reporter.report(f, states)
4594
end
95+
end
4696

47-
reporter = Lrama::TraceReporter.new(grammar)
48-
reporter.report(**options.trace_opts)
97+
def render_diagram(grammar)
98+
return unless @options.diagram
4999

50-
File.open(options.outfile, "w+") do |f|
100+
File.open(@options.diagram_file, "w+") do |f|
101+
Lrama::Diagram.render(out: f, grammar: grammar)
102+
end
103+
end
104+
105+
def render_output(context, grammar)
106+
File.open(@options.outfile, "w+") do |f|
51107
Lrama::Output.new(
52108
out: f,
53-
output_file_path: options.outfile,
54-
template_name: options.skeleton,
55-
grammar_file_path: options.grammar_file,
56-
header_file_path: options.header_file,
109+
output_file_path: @options.outfile,
110+
template_name: @options.skeleton,
111+
grammar_file_path: @options.grammar_file,
112+
header_file_path: @options.header_file,
57113
context: context,
58114
grammar: grammar,
59-
error_recovery: options.error_recovery,
115+
error_recovery: @options.error_recovery,
60116
).render
61117
end
62-
63-
logger = Lrama::Logger.new
64-
exit false unless Lrama::GrammarValidator.new(grammar, states, logger).valid?
65-
Lrama::Diagnostics.new(grammar, states, logger).run(options.diagnostic)
66118
end
67119
end
68120
end

tool/lrama/lib/lrama/context.rb

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# frozen_string_literal: true
22

3-
require_relative "report/duration"
3+
require_relative "tracer/duration"
44

55
module Lrama
66
# This is passed to a template
77
class Context
8-
include Report::Duration
8+
include Tracer::Duration
99

1010
ErrorActionNumber = -Float::INFINITY
1111
BaseMin = -Float::INFINITY
@@ -231,8 +231,8 @@ def compute_yydefact
231231
end
232232

233233
# Shift is selected when S/R conflict exists.
234-
state.selected_term_transitions.each do |shift, next_state|
235-
actions[shift.next_sym.number] = next_state.id
234+
state.selected_term_transitions.each do |shift|
235+
actions[shift.next_sym.number] = shift.to_state.id
236236
end
237237

238238
state.resolved_conflicts.select do |conflict|
@@ -292,18 +292,18 @@ def compute_yydefgoto
292292
# of a default nterm transition destination.
293293
@yydefgoto = Array.new(@states.nterms.count, 0)
294294
# Mapping from nterm to next_states
295-
nterm_to_next_states = {}
295+
nterm_to_to_states = {}
296296

297297
@states.states.each do |state|
298-
state.nterm_transitions.each do |shift, next_state|
299-
key = shift.next_sym
300-
nterm_to_next_states[key] ||= []
301-
nterm_to_next_states[key] << [state, next_state] # [from_state, to_state]
298+
state.nterm_transitions.each do |goto|
299+
key = goto.next_sym
300+
nterm_to_to_states[key] ||= []
301+
nterm_to_to_states[key] << [state, goto.to_state] # [from_state, to_state]
302302
end
303303
end
304304

305305
@states.nterms.each do |nterm|
306-
if (states = nterm_to_next_states[nterm])
306+
if (states = nterm_to_to_states[nterm])
307307
default_state = states.map(&:last).group_by {|s| s }.max_by {|_, v| v.count }.first
308308
default_goto = default_state.id
309309
not_default_gotos = []
@@ -417,27 +417,25 @@ def compute_packed_table
417417

418418
res = lowzero - froms_and_tos.first[0]
419419

420+
# Find the smallest `res` such that `@table[res + from]` is empty for all `from` in `froms_and_tos`
420421
while true do
421-
ok = true
422+
advanced = false
422423

423-
froms_and_tos.each do |from, to|
424-
loc = res + from
425-
426-
if @table[loc]
427-
# If the cell of table is set, can not use the cell.
428-
ok = false
429-
break
430-
end
424+
while used_res[res]
425+
res += 1
426+
advanced = true
431427
end
432428

433-
if ok && used_res[res]
434-
ok = false
429+
froms_and_tos.each do |from, to|
430+
while @table[res + from]
431+
res += 1
432+
advanced = true
433+
end
435434
end
436435

437-
if ok
436+
unless advanced
437+
# no advance means that the current `res` satisfies the condition
438438
break
439-
else
440-
res += 1
441439
end
442440
end
443441

0 commit comments

Comments
 (0)