class ErlangConfigParser::Parser
rule
statement : list | tuple list : LIST_BEGIN elements LIST_END { result = val[1] } | LIST_BEGIN LIST_END { result = [] } tuple : TUPLE_BEGIN elements TUPLE_END { result = val[1] } | TUPLE_BEGIN TUPLE_END { result = [] } elements : element { result = [val[0]] } | elements COMMA element { result << val[2] } element : list | tuple | ATOM { result = val[0].to_sym } | STRING { result = val[0] } | INTEGER { result = val[0].to_i } | FLOAT { result = val[0].to_f }
end
—- header require “strscan”
—- inner
def parse(str)
ss = StringScanner.new(str) @tokens = [] until ss.eos? ss.scan(/"((?:[^"\\]|\\.)*)"/) ? @tokens << [:STRING, ss[1]] : ss.scan(/[+-]?\d+\.\d+(?:e[+-]\d+)?/) ? @tokens << [:FLOAT, ss.matched] : ss.scan(/[+-]?\d+/) ? @tokens << [:INTEGER, ss.matched] : ss.scan(/\[/) ? @tokens << [:LIST_BEGIN, ss.matched] : ss.scan(/\]/) ? @tokens << [:LIST_END, ss.matched] : ss.scan(/{/) ? @tokens << [:TUPLE_BEGIN, ss.matched] : ss.scan(/}/) ? @tokens << [:TUPLE_END, ss.matched] : ss.scan(/'((?:[^'\\]|\\.)*)'/) ? @tokens << [:ATOM, ss[1]] : ss.scan(/[a-z][\w_@]*/) ? @tokens << [:ATOM, ss.matched] : ss.scan(/,/) ? @tokens << [:COMMA, ss.matched] : ss.scan(/\s/) ? nil : ss.scan(/\./) ? break : (raise "scanner error") end do_parse
end
def next_token
@tokens.shift
end