树顶布尔逻辑运算

时间:2015-09-03 10:24:23

标签: ruby treetop

我正在实现具有语法的DSL:

"[keyword] or ([other keyword] and not [one more keyword])"

每个关键字都会转换为布尔值(truefalse)值,之后应使用运算符and, or, not计算

我当前的语法规则仅匹配字符串[keyword] or [other keyword],并且在叮咬[keyword] or [other keyword] or [one more keyword]

时失败

如何编写符合任何orand构造的语法?

语法:

grammar Sexp

  rule expression
    keyword operand keyword <ExpressionLiteral>
  end

  rule operand
   or / and <OperandLiteral>
  end

  rule or
    'or' <OrLiteral>
  end

  rule and
    'and' <AndLiteral>
  end

  rule keyword
    space '[' ( '\[' / !']' . )* ']' space <KeywordLiteral>
  end

 rule space
   ' '*
 end
end

更新

Parser class

class Parser
  require 'treetop'
  base_path = File.expand_path(File.dirname(__FILE__))
  require File.join(base_path, 'node_extensions.rb')
  Treetop.load(File.join(base_path, 'sexp_parser.treetop'))

  def  self.parse(data)
    if data.respond_to? :read
      data = data.read
    end

    parser =SexpParser.new
    ast = parser.parse data

    if ast
      #self.clean_tree(ast)
      return ast
    else
      parser.failure_reason =~ /^(Expected .+) after/m
      puts "#{$1.gsub("\n", '$NEWLINE')}:"
      puts data.lines.to_a[parser.failure_line - 1]
      puts "#{'~' * (parser.failure_column - 1)}^"
    end
  end
    private
    def self.clean_tree(root_node)
       return if(root_node.elements.nil?)
       root_node.elements.delete_if{|node| node.class.name == "Treetop::Runtime::SyntaxNode" }
       root_node.elements.each {|node| self.clean_tree(node) }
    end
end

tree = Parser.parse('[keyword] or [other keyword] or [this]')
p tree
p tree.to_array

节点扩展

module Sexp
  class KeywordLiteral < Treetop::Runtime::SyntaxNode
    def to_array
      self.text_value.gsub(/[\s\[\]]+/, '')
    end
  end

  class OrLiteral < Treetop::Runtime::SyntaxNode
    def to_array
      self.text_value
    end
  end

  class AndLiteral < Treetop::Runtime::SyntaxNode
    def to_array
      self.text_value
    end
  end

  class OperandLiteral < Treetop::Runtime::SyntaxNode
    def to_array
      self.elements.map{|e| e.to_array}
    end
  end

  class ExpressionLiteral < Treetop::Runtime::SyntaxNode
    def to_array
      self.elements.map{|e| e.to_array}.join(' ')
    end
  end
end

0 个答案:

没有答案