-
Notifications
You must be signed in to change notification settings - Fork 27
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
Add lexer.rbs #33
base: master
Are you sure you want to change the base?
Add lexer.rbs #33
Conversation
@@ -18,8 +20,8 @@ def to_s | |||
"#{super} line: #{line}, column: #{column}" | |||
end | |||
|
|||
@i = 0 | |||
@types = [] | |||
instance_variable_set :@i, 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[note] steep can not detect a type of instance variable for original codes, even so rbs file has declarations for them. It might the limitation for Struct with block (?).
lib/lrama/lexer.rb:23:6: [error] Cannot find the declaration of instance variable: `@i`
│ Diagnostic ID: Ruby::UnknownInstanceVariable
│
└ @i = 0
~~
lib/lrama/lexer.rb:24:6: [error] Cannot find the declaration of instance variable: `@types`
│ Diagnostic ID: Ruby::UnknownInstanceVariable
│
└ @types = []
~~~~~~
Detected 2 problems from 1 file
@@ -62,8 +64,7 @@ def self.define_type(name) | |||
GrammarRules = 3 | |||
Epilogue = 4 | |||
|
|||
# Token types | |||
|
|||
# @dynamic prologue, bison_declarations, grammar_rules, epilogue, bison_declarations_tokens, grammar_rules_tokens |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my environment bundle exec steep check
passes without this annotation. Is there any benefit for these annotation?
Token = Struct.new(:type, :s_value, keyword_init: true) do | ||
Type = Struct.new(:id, :name, keyword_init: true) | ||
Token = _ = Struct.new(:type, :s_value, keyword_init: true) do | ||
# @implements Token[SValue] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[note] This is an annotation defined in steep not rbs.
@@ -7,8 +7,10 @@ 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) | |||
Token = _ = Struct.new(:type, :s_value, keyword_init: true) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[note] Inserting _
between a constant and Struct.new
is a common workaround when we use Struct
to define new class.
type line_data = [String, Integer] | ||
type reference = [::Symbol, Integer | String, Token[untyped]?, Integer, Integer] | ||
|
||
class Type[SValue] < Struct[untyped] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need SValue
type variable? Always Type#id
is Interger and Type#name
is String.
>> Lrama::Lexer::Token::P_expect
=> #<struct Lrama::Lexer::Type id=0, name="P_expect">
>> Lrama::Lexer::Token::Number
=> #<struct Lrama::Lexer::Type id=15, name="Number">
On the other hand. Token
needs type variable because type of s_value
depends on the value of Type
.
|
def lex_common: (Array[line_data] lines, Array[Token[untyped]] tokens) -> void | ||
def lex_bison_declarations_tokens: -> void | ||
def lex_user_code: (StringScanner, Integer line, Integer column, Array[line_data] lines) -> [Token[String], Integer] | ||
def lex_string: (StringScanner, String terminator, Integer line, Array[line_data] lines) -> line_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely, the type of returned value is [String, Integer]
. But this string is a part of line
so I'm wondering which is better to use line_data
type or [String, Integer]
. Do you have any opinion?
Added lexer.rbs.
Discussions:
Type
andToken
have type parameters namedSValue
. I expect them to work well in parser.rb.create_token(Token::Number, str, ...)
untypable.patch.rbs
, which patches the types ofStringScanner#[]
andStringScanner#getch
.StringScanner#fetch
andStringScanner#getch!
, as soutaro remarked.ss[n]
with(ss[n] || raise)
and so on, but that would be hard to read.Array#[]
andArray#first
becauseArray
is used widely, and such patches may affect other files. Instead, I replacedarray[0...l]
witharray.take(l)
andarray.first
witharray.fetch(0)
.