Skip to content

Instantly share code, notes, and snippets.

@trairia
Last active June 24, 2016 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trairia/daba80eeb8cbba00705a655641eb3f56 to your computer and use it in GitHub Desktop.
Save trairia/daba80eeb8cbba00705a655641eb3f56 to your computer and use it in GitHub Desktop.
require 'parslet'
require 'pp'
class SVNumberParser < Parslet::Parser
rule(:x_digit){ match('[xX]') }
rule(:z_digit){ match('[zZ?]') }
rule(:underscore){ str('_') }
rule(:nz_dec_digit){ match('[0-9]') }
rule(:dec_digit) { str('0') | nz_dec_digit }
rule(:nz_uint) { nz_dec_digit >> (underscore | dec_digit).repeat }
# signal bit width
rule(:size?) { nz_uint.maybe.as(:size) }
rule(:signed_base) { match('[sS]') }
rule(:quote) { str('\'') }
def self.num_rule(define)
define.each do |d|
rule("#{d[:name]}_digit") { x_digit | z_digit | match(d[:digit]) }
rule("#{d[:name]}_val") {
eval("#{d[:name]}_digit") >> (underscore | eval("#{d[:name]}_digit")).repeat
}
rule("#{d[:name]}_base") {
signed_base.maybe >> match(d[:base])
}
rule("#{d[:name]}_number") {
size? >> quote >>
self.instance_eval("#{d[:name]}_base").as(:base) >>
self.instance_eval("#{d[:name]}_val").as(:value)
}
end
end
num_rule [{name: "binary", base: '[bB]', digit: '[01]'},
{name: "octal", base: '[oO]', digit: '[0-7]'},
{name: "hex", base: '[hH]', digit: '\h'}]
rule(:unsigned_number){ dec_digit >> (underscore | dec_digit).repeat }
rule(:decimal_base) { signed_base.maybe >> match('[dD]') }
rule(:decimal_number) {
dec_number = unsigned_number.as(:value)
dec_number = dec_number | size? >> quote >> decimal_base >> unsigned_number.as(:value)
dec_number = dec_number | size? >> quote >> decimal_base >>
x_digit.as(:value) >> underscore.repeat
dec_number = dec_number | size? >> quote >> decimal_base >> z_digit >> underscore.repeat
dec_number
}
rule(:integral_number){
hex_number | decimal_number | octal_number | binary_number
}
root(:integral_number)
end
require 'pp'
parser = SVNumberParser.new
test = [
"'b1",
"4'hx",
"8'hz",
"2'b11",
"8'b1111_1111",
"32",
"10'd1023"
]
test.each do |str|
pp parser.parse(str)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment