在树梢上找到单词 - 有些比赛没有被发现

时间:2011-08-22 20:03:38

标签: ruby treetop

我遇到了一些奇怪的情况。

我正在尝试使用树梢来解析测量结果。

例如 - 1/2英寸的“铜管” 当然,这也可以写成英尺,英尺,英寸,英寸,英寸等。

所以我有一个规则

rule measurement
      ('\'' / 'Foot' / 'foot' / 'Feet' / 'feet' / 
       '"' / 'Inches' / 'inches' /  'Inch' / 'inch' /
       'cm' / 'cms' / 'Centimeters' / 'centimeters' /  'Centimeter' / 'centimeter' / 
       'm' / 'ms' / 'Meters' / 'meters'/ 'Meter' / 'meter' / 
       'lb' / 'lbs' /  'Pounds' / 'pounds' / 'Pound' / 'pound' )
       (s? ')' / s) {
                    def value
                          [:measurement, text_value]
                    end
                    }
end

rule space
    [\s]+
end

当我输入'6英寸','6磅','6米'时,一切都很好,我得到了我的号码和测量结果。

当我输入'6米'时,米没有正确解析。

大多数测量工作正常,我在这里提供的测量中只忽略了“米”和“磅”(但我相信我将来会增加更多测量值。

关于为什么我会遇到这个问题的任何想法?

根据要求,完整语法的“减少”版本

grammar FullMeasurements
       rule full_product
           measures s? alternate_measure product_name {
             def value
                  [:full_product, text_value]
             end
           }

       end

       rule measures
        single_measure / dual_measure / quantity {
            def measures
                [:measures, text_value] unless text_value.blank?
            end
        }
    end


    rule dual_measure
        quantity s? single_measure {
            def value
                [:dual_measure, text_value] unless text_value.blank?
            end

            }
    end


    rule alternate_measure 
        '(' s? single_measure {
            def value
                [:alternate_measure, text_value] unless text_value.blank?
            end
        }
    end

    rule single_measure 
        (range_number / number) s? measurement optional_secondary_measurements  {
            def value
                [:single_measure, text_value]
            end
        }
    end

    rule optional_secondary_measurements
        measurement? {
            def value
                [:optional_secondary_measurements, text_value]
            end
        }
    end



    rule quantity
        (range_number / number) s? divisor? {
            def value
                [:quantity, text_value]
            end
        }
    end

        rule measurement
              ('\'' / 'Foot' / 'foot' / 'Feet' / 'feet' / 
               '"' / 'Inches' / 'inches' /  'Inch' / 'inch' /
               'cm' / 'cms' / 'Centimeters' / 'centimeters' /  'Centimeter' / 'centimeter' / 
               'm' / 'ms' / 'Meters' / 'meters'/ 'Meter' / 'meter' / 
               'lb' / 'lbs' /  'Pounds' / 'pounds' / 'Pound' / 'pound' )
                (s? ')' / s) {
                    def value
                          [:measurement, text_value]
                    end
                    }
         end



        rule divisor
        "x" 
    end

    rule product_name
            !measures words+ {
            def value
                [:product_name, text_value]
            end
        }
    end


    rule number 
     frac_number / regular_number optional_frac {
            def value
                [:number, text_value]
            end
        }
        end



        rule optional_frac
        frac_number? {
            def value
                [:optional_frac, text_value]
            end
        }
         end



         rule frac_number
        (s? regular_number '/' regular_number)  {
            def value
                [:frac_number, text_value]
            end
        }
        end

        rule words
        [0-9a-zA-Z\-()&.%'*\s]+ {
            def value
                text_value
            end 
        }

          end

        rule regular_number
        [0-9\.]+ {
            def value
                text_value
            end 
        }

        end

        rule space
          [\s]+
         end
end

2 个答案:

答案 0 :(得分:1)

由于PEG是贪婪的并且/有序交替,因此您的measurement规则与文字“meter”相匹配,然后您的语法失败,因为它无法找到以下内容与左边的“s”匹配的规则。与正则表达式不同,当后一个成功匹配失败时,PEG不会回溯之前的成功匹配。

将规则中的项目顺序切换为复数,然后你应该好好去。

答案 1 :(得分:0)

Phrogz在正确的轨道上,但它并不是“米”首先匹配,而是“m”没有任何东西可以匹配剩下的“eter”或“eters”。