Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
require "rly"
class Lexer < Rly::Lex
literals '{}(),;='
ignore " \t\n"
token :T_OBJECTID, /[\w\.]+:\"*\w*\"*:\w+/
token :T_NUMBER, /\d+/
token :T_NULL, /NULL(?=[^\w])/
token :T_BOOLEAN, /[TF]{1}(?=[^\w])/
token :T_IDENTIFIER, /\w+/
token :T_STRING, /\".*?(?<!\\)\"/m
token :T_REFERENCE, /\<.*?\>/
end
require "rly"
class Parser < Rly::Yacc
rule 'input: object' do |*t|
t[0].value = t[1].value
end
rule 'object: T_OBJECTID "{" attributes "}"' do |*t|
oid = t[1].value.split(':')
t[0].value = {
:id => dequote(oid[0]),
:name => convertNULL(dequote(oid[1])),
:type => dequote(oid[2])
}.merge(t[3].value)
end
rule 'attributes: attribute | attributes attribute' do |*t|
case
when t[1].type == :attribute
t[0].value = t[1].value
when t[1].type == :attributes
t[0].value = t[1].value.merge(t[2].value)
end
end
rule 'attribute: T_IDENTIFIER "=" value ";"' do |*t|
t[0].value = {t[1].value => t[3].value}
end
rule 'values: value | values "," value' do |*t|
case
when t[1].type == :value
t[0].value = [t[1].value]
when t[1].type == :values
t[0].value = t[1].value.concat([t[3].value])
end
end
rule 'value: T_STRING |
T_REFERENCE |
T_NUMBER |
T_BOOLEAN |
T_NULL |
"{" object "}" |
"(" values ")"' do |*t|
case
when t[1].type == :T_STRING || t[1].type == :T_REFERENCE
t[0].value = dequote(t[1].value)
when t[1].type == :T_NUMBER
t[0].value = t[1].value.to_i
when t[1].type == :T_BOOLEAN
t[0].value = t[1].value == 'T'
when t[1].type == :T_NULL
t[0].value = nil
when t[2].type == :object || t[2].type == :values
t[0].value = t[2].value
end
end
def dequote(text)
text.gsub(/\A["<]|[">]\Z/, '').strip
end
def convertNULL(text)
text.upcase == "NULL" ? nil : text
end
end
Практическое использование Racc — генератора LALR(1) парсера для Ruby