Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up rbs_collection.yaml and add a TypeProf-generated prototype rbs #19

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle install
- run: bundle exec rbs collection install
- run: bundle exec steep check
test-ruby:
runs-on: ubuntu-20.04
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.irbrc
/Gemfile.lock
/pkg/
/.gem_rbs_collection/
11 changes: 8 additions & 3 deletions Steepfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# D = Steep::Diagnostic
#
D = Steep::Diagnostic

target :lib do
signature "sig"

check "lib/lrama/bitmap.rb"
configure_code_diagnostics do |hash|
hash[D::Ruby::ImplicitBreakValueMismatch] = :hint
hash[D::Ruby::ElseOnExhaustiveCase] = :hint
end

check "lib/lrama/"
end
23 changes: 13 additions & 10 deletions lib/lrama/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ def yytable_ninf
end

def yypact
@base[0...yynstates]
@base[0...yynstates] || raise
end

def yydefact
@yydefact
end

def yypgoto
@base[yynstates..-1]
@base[yynstates..-1] || raise
end

def yydefgoto
Expand Down Expand Up @@ -227,6 +227,7 @@ def compute_yydefact
# * number = -Float::INFINITY, error by %nonassoc
# * number > 0, shift then move to state "number"
# * number < 0, reduce by "-number" rule. Rule "number" is already added by 1.
# @type var actions: Array[Integer | Float]
actions = Array.new(@states.terms.count, 0)

if state.reduces.map(&:selected_look_ahead).any? {|la| !la.empty? }
Expand Down Expand Up @@ -273,9 +274,11 @@ def compute_yydefact
end
end

# @type var s: Array[[Integer, Integer]]
s = actions.each_with_index.map do |n, i|
[i, n]
end.select do |i, n|
[i, n] #: [Integer, Integer]
end
s = s.select do |i, n|
# Remove default_reduction_rule entries
n != 0
end
Expand All @@ -287,10 +290,10 @@ def compute_yydefact
# * Array of tuple, [from, to] where from is term number and to is action.
# * The number of "Array of tuple" used by sort_actions
# * "width" used by sort_actions
@_actions << [state.id, s, s.count, s.last[0] - s.first[0] + 1]
@_actions << [state.id, s, s.count, (s.last || raise)[0] - (s.first || raise)[0] + 1]
end

@yydefact[state.id] = state.default_reduction_rule ? state.default_reduction_rule.id + 1 : 0
(@yydefact || raise)[state.id] = state.default_reduction_rule ? state.default_reduction_rule.id + 1 : 0
end
end

Expand Down Expand Up @@ -327,7 +330,7 @@ def compute_yydefgoto
end

k = nterm_number_to_sequence_number(nterm.number)
@yydefgoto[k] = default_goto
(@yydefgoto || raise)[k] = default_goto

if not_default_gotos.count != 0
v = nterm_number_to_vector_number(nterm.number)
Expand Down Expand Up @@ -427,7 +430,7 @@ def compute_packed_table
next
end

res = lowzero - froms_and_tos.first[0]
res = lowzero - (froms_and_tos.first || raise)[0]

while true do
ok = true
Expand Down Expand Up @@ -476,7 +479,7 @@ def compute_packed_table
@yylast = high

# replace_ninf
@yypact_ninf = (@base.select {|i| i != BaseMin } + [0]).min - 1
@yypact_ninf = ((@base.select {|i| i != BaseMin } + [0]).min || raise) - 1
@base.map! do |i|
case i
when BaseMin
Expand All @@ -486,7 +489,7 @@ def compute_packed_table
end
end

@yytable_ninf = (@table.compact.select {|i| i != ErrorActionNumber } + [0]).min - 1
@yytable_ninf = ((@table.compact.select {|i| i != ErrorActionNumber } + [0]).min || raise) - 1
@table.map! do |i|
case i
when nil
Expand Down
2 changes: 1 addition & 1 deletion lib/lrama/digraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def traverse(x)

@relation[x] && @relation[x].each do |y|
traverse(y) if @h[y] == 0
@h[x] = [@h[x], @h[y]].min
@h[x] = [@h[x], @h[y]].min || raise
@result[x] |= @result[y] # F x = F x + F y
end

Expand Down
58 changes: 33 additions & 25 deletions lib/lrama/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require "lrama/lexer"

module Lrama
Rule = Struct.new(:id, :lhs, :rhs, :code, :nullable, :precedence_sym, :lineno, keyword_init: true) do
class Rule < Struct.new(:id, :lhs, :rhs, :code, :nullable, :precedence_sym, :lineno, keyword_init: true)
# TODO: Change this to display_name
def to_s
l = lhs.id.s_value
Expand Down Expand Up @@ -41,7 +41,7 @@ def translated_code
# `token_id` is tokentype for term, internal sequence number for nterm
#
# TODO: Add validation for ASCII code range for Token::Char
Symbol = Struct.new(:id, :alias_name, :number, :tag, :term, :token_id, :nullable, :precedence, :printer, keyword_init: true) do
class Symbol < Struct.new(:id, :alias_name, :number, :tag, :term, :token_id, :nullable, :precedence, :printer, keyword_init: true)
attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol

def term?
Expand Down Expand Up @@ -89,19 +89,19 @@ def enum_name
if alias_name
name = number.to_s + alias_name
else
name = number.to_s + id.s_value
name = number.to_s + id.s_value_str
end
when term? && id.type == Token::Ident
name = id.s_value
when nterm? && (id.s_value.include?("$") || id.s_value.include?("@"))
name = number.to_s + id.s_value
name = id.s_value_str
when nterm? && (id.s_value_str.include?("$") || id.s_value_str.include?("@"))
name = number.to_s + id.s_value_str
when nterm?
name = id.s_value
name = id.s_value_str
else
raise "Unexpected #{self}"
end

"YYSYMBOL_" + name.gsub(/[^a-zA-Z_0-9]+/, "_")
"YYSYMBOL_" + (name || raise).gsub(/[^a-zA-Z_0-9]+/, "_")
end

# comment for yysymbol_kind_t
Expand All @@ -113,22 +113,23 @@ def comment
when eof_symbol?
# YYEOF
alias_name
when (term? && 0 < token_id && token_id < 128)
when (term? && 0 < (token_id || raise) && (token_id || raise) < 128)
# YYSYMBOL_3_backslash_, YYSYMBOL_14_
alias_name || id.s_value
when id.s_value.include?("$") || id.s_value.include?("@")
when id.s_value_str.include?("$") || id.s_value_str.include?("@")
# YYSYMBOL_21_1
id.s_value
id.s_value_str
else
# YYSYMBOL_keyword_class, YYSYMBOL_strings_1
alias_name || id.s_value
alias_name || id.s_value_str
end
end
end

Type = Struct.new(:id, :tag, keyword_init: true)
class Type < Struct.new(:id, :tag, keyword_init: true)
end

Code = Struct.new(:type, :token_code, keyword_init: true) do
class Code < Struct.new(:type, :token_code, keyword_init: true)
extend Forwardable

def_delegators "token_code", :s_value, :line, :column, :references
Expand Down Expand Up @@ -166,7 +167,7 @@ def translated_printer_code(tag)
when ref.type == :at # @n
raise "@#{ref.number} can not be used in %printer."
else
raise "Unexpected. #{code}, #{ref}"
raise "Unexpected. #{self}, #{ref}"
end

t_code[first_column..last_column] = str
Expand Down Expand Up @@ -205,7 +206,7 @@ def translated_user_code
i = -ref.position_in_rhs + ref.number
str = "(yylsp[#{i}])"
else
raise "Unexpected. #{code}, #{ref}"
raise "Unexpected. #{self}, #{ref}"
end

t_code[first_column..last_column] = str
Expand Down Expand Up @@ -235,7 +236,7 @@ def translated_initial_action_code
when ref.type == :at # @n
raise "@#{ref.number} can not be used in initial_action."
else
raise "Unexpected. #{code}, #{ref}"
raise "Unexpected. #{self}, #{ref}"
end

t_code[first_column..last_column] = str
Expand All @@ -247,7 +248,7 @@ def translated_initial_action_code

# type: :dollar or :at
# ex_tag: "$<tag>1" (Optional)
Reference = Struct.new(:type, :number, :ex_tag, :first_column, :last_column, :referring_symbol, :position_in_rhs, keyword_init: true) do
class Reference < Struct.new(:type, :number, :ex_tag, :first_column, :last_column, :referring_symbol, :position_in_rhs, keyword_init: true)
def tag
if ex_tag
ex_tag
Expand All @@ -257,21 +258,21 @@ def tag
end
end

Precedence = Struct.new(:type, :precedence, keyword_init: true) do
class Precedence < Struct.new(:type, :precedence, keyword_init: true)
include Comparable

def <=>(other)
self.precedence <=> other.precedence
end
end

Printer = Struct.new(:ident_or_tags, :code, :lineno, keyword_init: true) do
class Printer < Struct.new(:ident_or_tags, :code, :lineno, keyword_init: true)
def translated_code(member)
code.translated_printer_code(member)
end
end

Union = Struct.new(:code, :lineno, keyword_init: true) do
class Union < Struct.new(:code, :lineno, keyword_init: true)
def braces_less_code
# Remove braces
code.s_value[1..-2]
Expand All @@ -283,7 +284,8 @@ def braces_less_code
# Grammar is the result of parsing an input grammar file
class Grammar
# Grammar file information not used by States but by Output
Aux = Struct.new(:prologue_first_lineno, :prologue, :epilogue_first_lineno, :epilogue, keyword_init: true)
class Aux < Struct.new(:prologue_first_lineno, :prologue, :epilogue_first_lineno, :epilogue, keyword_init: true)
end

attr_reader :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux
attr_accessor :union, :expect,
Expand Down Expand Up @@ -565,7 +567,7 @@ def append_special_symbols

# $accept
term = add_nterm(id: Token.new(type: Token::Ident, s_value: "$accept"))
term.accept_symbol = true
(term || raise).accept_symbol = true
@accept_symbol = term
end

Expand Down Expand Up @@ -595,15 +597,18 @@ def normalize_rules
# 1. Add $accept rule to the top of rules
accept = find_symbol_by_s_value!("$accept")
eof = find_symbol_by_number!(0)
lineno = @_rules.first ? @_rules.first[2] : 0
@rules << Rule.new(id: @rules.count, lhs: accept, rhs: [@_rules.first[0], eof], code: nil, lineno: lineno)
lineno = @_rules.first ? (@_rules.first || raise)[2] : 0
@rules << Rule.new(id: @rules.count, lhs: accept, rhs: [(@_rules.first || raise)[0], eof], code: nil, lineno: lineno)

extracted_action_number = 1 # @n as nterm

@_rules.each do |lhs, rhs, lineno|
# @type var a: Array[[Token, Token]]
a = []
rhs1 = []
# @type var code: Token?
code = nil
# @type var precedence_sym: Symbol?
precedence_sym = nil

# 2. Extract precedence and last action
Expand Down Expand Up @@ -672,6 +677,7 @@ def normalize_rules
# Collect symbols from rules
def collect_symbols
@rules.flat_map(&:rhs).each do |s|
# @type var s: Token | Symbol
case s
when Token
if s.type == Token::Char
Expand Down Expand Up @@ -704,6 +710,7 @@ def fill_symbol_number
end

(@symbols.select(&:term?) + @symbols.select(&:nterm?)).each do |sym|
# @type var sym: Symbol
while used_numbers[number] do
number += 1
end
Expand Down Expand Up @@ -795,6 +802,7 @@ def fill_default_precedence
# Explicitly specified precedence has the highest priority
next if rule.precedence_sym

# @type var precedence_sym: Symbol?
precedence_sym = nil
rule.rhs.each do |sym|
precedence_sym = sym if sym.term?
Expand Down
24 changes: 18 additions & 6 deletions lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,20 @@ class Lexer
include Lrama::Report::Duration

# s_value is semantic value
Token = Struct.new(:type, :s_value, keyword_init: true) do
Type = Struct.new(:id, :name, keyword_init: true)
class Token < Struct.new(:type, :s_value, keyword_init: true)
def s_value_int
s = s_value
raise unless s.is_a?(Integer)
s
end
def s_value_str
s = s_value
raise unless s.is_a?(String)
s
end

class Type < Struct.new(:id, :name, keyword_init: true)
end

attr_accessor :line, :column, :referred
# For User_code
Expand Down Expand Up @@ -219,7 +231,7 @@ def lex_common(lines, tokens)
else
l = line - lines.first[1]
split = ss.string.split("\n")
col = ss.pos - split[0...l].join("\n").length
col = ss.pos - (split[0...l] || raise).join("\n").length
raise "Parse error (unknown token): #{split[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{col})"
end
end
Expand Down Expand Up @@ -283,7 +295,7 @@ def lex_user_code(ss, line, column, lines)
line = lex_line_comment(ss, line, str)
else
# noop, just consume char
str << ss.getch
str << (ss.getch || raise)
next
end

Expand Down Expand Up @@ -328,7 +340,7 @@ def lex_comment(ss, line, lines, str)
when ss.scan(/\*\//)
return line
else
str << ss.getch
str << (ss.getch || raise)
next
end

Expand All @@ -347,7 +359,7 @@ def lex_line_comment(ss, line, str)
when ss.scan(/\n/)
return line + 1
else
str << ss.getch
str << (ss.getch || raise)
next
end

Expand Down
Loading