class InterMine::PathQuery::LogicParser

Attributes

ops[RW]
precedence[RW]

Public Class Methods

new(query) click to toggle source
     # File lib/intermine/query.rb
1489 def initialize(query)
1490     @query = query
1491 end

Public Instance Methods

parse_logic(str) click to toggle source
     # File lib/intermine/query.rb
1493 def parse_logic(str)
1494     tokens = str.upcase.split(/(?:\s+|\b)/).map do |x| 
1495         LogicParser.ops.fetch(x, x.split(//))
1496     end
1497     tokens.flatten!
1498 
1499     check_syntax(tokens)
1500     postfix_tokens = infix_to_postfix(tokens)
1501     ast = postfix_to_tree(postfix_tokens)
1502     return ast
1503 end

Private Instance Methods

check_syntax(tokens) click to toggle source
     # File lib/intermine/query.rb
1549 def check_syntax(tokens)
1550     need_op = false
1551     need_bin_op_or_bracket = false
1552     processed = []
1553     open_brackets = 0
1554     tokens.each do |x|
1555         if !LogicParser.ops.include?(x)
1556             if need_op
1557                 raise LogicParseError, "Expected an operator after '#{processed.join(' ')}', but got #{x}"
1558             elsif need_bin_op_or_bracket
1559                 raise LogicParseError, "Logic grouping error after '#{processed.join(' ')}', expected an operator or closing bracket, but got #{x}"
1560             end
1561             need_op = true
1562         else
1563             need_op = false
1564             case x
1565             when "("
1566                 if !processed.empty? && !LogicParser.ops.include?(processed.last)
1567                     raise LogicParseError, "Logic grouping error after '#{processed.join(' ')}', got #{x}"
1568                 elsif need_bin_op_or_bracket
1569                     raise LogicParseError, "Logic grouping error after '#{processed.join(' ')}', got #{x}"
1570                 end
1571                 open_brackets += 1
1572             when ")"
1573                 need_bin_op_or_bracket = true
1574                 open_brackets -= 1
1575             else
1576                 need_bin_op_or_bracket = false
1577             end
1578         end
1579         processed << x
1580     end
1581     if open_brackets < 0
1582         raise LogicParseError, "Unmatched closing bracket in #{tokens.join(' ')}"
1583     elsif open_brackets > 0
1584         raise LogicParseError, "Unmatched opening bracket in #{tokens.join(' ')}"
1585     end
1586 end
infix_to_postfix(tokens) click to toggle source
     # File lib/intermine/query.rb
1507 def infix_to_postfix(tokens)
1508     stack = []
1509     postfix_tokens = []
1510     tokens.each do |x|
1511         if !LogicParser.ops.include?(x)
1512             postfix_tokens << x
1513         else
1514             case x
1515             when "("
1516                 stack << x
1517             when ")"
1518                 while !stack.empty?
1519                     last_op = stack.pop
1520                     if last_op == "("
1521                         if !stack.empty?
1522                             previous_op = stack.pop
1523                             if previous_op != "("
1524                                 postfix_tokens << previous_op
1525                                 break
1526                             end
1527                         end
1528                     else 
1529                         postfix_tokens << last_op
1530                     end
1531                 end
1532             else
1533                 while !stack.empty? and LogicParser.precedence[stack.last] <= LogicParser.precedence[x]
1534                     prev_op = stack.pop
1535                     if prev_op != "("
1536                         postfix_tokens << prev_op
1537                     end
1538                 end
1539                 stack << x
1540             end
1541         end
1542     end
1543     while !stack.empty?
1544         postfix_tokens << stack.pop
1545     end
1546     return postfix_tokens
1547 end
postfix_to_tree(tokens) click to toggle source
     # File lib/intermine/query.rb
1588 def postfix_to_tree(tokens)
1589     stack = []
1590     tokens.each do |x|
1591         if !LogicParser.ops.include?(x)
1592             stack << x
1593         else
1594             right = stack.pop
1595             left = stack.pop
1596             right = (right.is_a?(LogicGroup)) ? right : @query.get_constraint(right)
1597             left = (left.is_a?(LogicGroup)) ? left : @query.get_constraint(left)
1598             stack << LogicGroup.new(left, x, right)
1599         end
1600     end
1601     if stack.size != 1
1602         raise LogicParseError, "Tree does not have a unique root"
1603     end
1604     return stack.pop
1605 end
precedence_of(op) click to toggle source
     # File lib/intermine/query.rb
1607 def precedence_of(op)
1608     return LogicParser.precedence[op]
1609 end