简体   繁体   English

树顶布尔逻辑运算

[英]Treetop boolean logic operations

I am implementing DSL which has syntax: 我正在实现具有语法的DSL:

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

Each keyword will transform to boolean ( true , false ) value and after that it should be calculated using operators and, or, not 每个关键字都将转换为布尔值( truefalse ),之后应使用运算符and, or, not

My current grammar rules match only strings [keyword] or [other keyword] and fails on stings [keyword] or [other keyword] or [one more keyword] 我当前的语法规则只匹配字符串[keyword] or [other keyword]并且在stings [keyword] or [other keyword] or [one more keyword]上失败

How to write grammar that match any ammount of or , and constructions? 如何写匹配任何ammount的是语法orand结构?

Grammar: 语法:

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

Updates 更新

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

node extension 节点扩展

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

Ok, thanks for that clarification. 好的,谢谢你的澄清。 In Ruby, "false and true or true" is true, because the "and" is evaluated first (it has higher precedence). 在Ruby中,“false和true或true”是正确的,因为首先评估“and”(它具有更高的优先级)。 To parse this, you need one rule for the "or" list (the disjunctions) which calls another rule for the "and" list (the conjunctions). 要解析这个,你需要一个规则用于“或”列表(析取),它为“和”列表(连词)调用另一个规则。 Like this: 像这样:

rule expression
  s disjunction s
  { def value; disjunction.value; end }
end

rule disjunction
  conjunction tail:(or s conjunction s)*
  { def value
      tail.elements.inject(conjunction.value) do |r, e|
        r or e.conjunction.value
      end
    end
  }
end

rule conjunction
  primitive tail:(and s primitive s)*
  { def value
      tail.elements.inject(primitive.value) do |r, e|
        r and e.primitive.value
      end
    end
  }
end

rule primitive
  '(' expression ')' s { def value; expression.value; end }
  /
  not expression  s { def value; not expression.value; end }
  /
  symbol s { def value; symbol.value; end }
end

rule or
  'or' !symbolchar s
end

rule and
  'and' !symbolchar s
end

rule not
  'not' !symbolchar s
end

rule symbol
  text:([[:alpha:]_] symbolchar*) s
  { def value
      lookup_value(text.text_value)
    end
  }
end

rule symbolchar
  [[:alnum:]_]
end

rule s # Optional space
  S?
end

rule S # Mandatory space
  [ \t\n\r]*
end

Note some things: 注意一些事情:

  • keywords must not be immediately followed by a symbol character. 关键字不能紧跟符号字符。 I use negative lookahead for this. 我为此使用负面预测。
  • The top rule consumes leading whitespace, then almost every rule consumes following whitespace (this is my policy). 最高规则消耗领先的空白,然后几乎每个规则都消耗以下空格(这是我的政策)。 You should test your grammar with minimum and maximum whitespace. 你应该用最小和最大的空格来测试你的语法。
  • There's no need to use a syntaxnode class on every rule, as you did. 就像你一样,不需要在每个规则上使用syntaxnode类。
  • You can see how to continue the pattern for addition, multiplication, etc 您可以看到如何继续添加,乘法等模式
  • I've given a sketch of some code that evaluates the expression. 我给出了一些评估表达式的代码草图。 Use something prettier please! 请使用更漂亮的东西!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM