ruby 解析器 - 示例解析器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 解析器 - 示例解析器相关的知识,希望对你有一定的参考价值。


##  Simple Parser
##
##  This parser implments an example of a parser similiar to Hoplon or Pollen
##  in that it translates an s expression to html
##  ie (h1 "The Great Gatsby") produces <h1>The Great Gatsby</h1>
#
#
# Input
#
#
#   Initial S Expression
#
# (html
#   (head
#     (title "Hello World"))
#   (body
#     (h1 "Hello World")
#     (p "This is your parser")))
#
#
# '(html(head(title "Hello World"))(body (h1 "Hello World")(p "This is your parser")))'
#
##  Converted to nested array of symbols  with class Reader
##
## parse_string   ==
## [:html, [:head, [:title, "Hello World"]], [:body, [:h1, "Hello World"], [:p, "This is your parser"]]]
##
##
###      Finally to HTML
###
### <html>
###      <head>
###          <title>Hello World</title>
###        </head>
###      <body>
###        <h1> Hello World </h1>
###        <p> This is your parser</p>
###      </body>
### </html>



require 'strscan'

class Reader < StringScanner


  # Check for Missing parens


  def initialize(string)
    unless(string.count('(') == string.count(')'))
      raise Exception, "Missing closing parentheses"
    end
    super(string)
  end


  #  Pull the tokens from the S_Exp into an Array

  def parse
    exp = []
    while true
      case fetch_token
      when '('
        exp << parse
      when ')'
        break
      when :"'"
        case fetch_token
        when '(' then exp << [:quote].concat([parse])
        else exp << [:quote, @token]
        end
      when String, Fixnum, Symbol
        exp << @token
      when nil
        break
      end
    end
    exp
  end

  # Use scan with regex to grab each token

  def fetch_token
    skip(/\s+/)
    return nil if(eos?)

    @token =

      # Match parentheses

    if scan(/[\(\)]/)
      matched

      # Match a string

    elsif scan(/"([^"\\]|\\.)*"/)
      eval(matched)

      # Match an integer

    elsif scan(/[\-\+]?[0-9]+/)
      matched.to_i

      # Match a single quote (for single quoting)

    elsif scan(/'/)
      matched.to_sym

      # Match a symbol

    elsif scan(/[^\(\)\s]+/)
      matched.to_sym

      # If we've gotten here then we have an invalid token

    else
      near = scan %r{.{0,20}}
      raise "Invalid character at position #{pos} near '#{near}'."
    end
  end
end

class Parser


  # Parse a string containing an S-Expression into a
  # nested set of Ruby arrays

  def parse_string(string)
    tree = Reader.new(string).parse
    tree = tree[0]     # pull off the outer Array
    return tree
  end


  def to_html(data)
    if (data.is_a?(Array))

      tag = data[0]
      children = data[1..-1]
      return "<#{tag}>" + children.map {|x| to_html(x)}.join(' ') + "</#{tag}>"
    else
      return data
    end
  end


  # Convert a set of nested arrays back into an S-Expression

  def to_sexp(data)
    if( data.is_a?(Array))
      mapped = data.map do |item|
        if( item.is_a?(Array))
          to_sexp(item)
        else
          item.to_s
        end
      end
      "(" + mapped.join(" ") + ")"
    else
      data.to_s
    end
  end

end

以上是关于ruby 解析器 - 示例解析器的主要内容,如果未能解决你的问题,请参考以下文章

ruby Ruby中的简单命令行解析器

用于自定义标记语言的 Ruby 标记解析器

ruby tomcat日志文件的解析器

ruby 自定义时间戳的时间解析器

Ruby命令行选项解析器

ruby 使用AnyStyle解析器从剪贴板解析引用,并将相应的bibtex记录返回到剪贴板