2010-03-04 10 views
5

나는 문자열 루비에 가장 좋은 방법은이 문자열을 구문 분석하는 방법을루비 구문 분석 문자열

input = "maybe (this is | that was) some ((nice | ugly) (day |night) | (strange (weather | time)))" 

있나요? 어쩌면이가 어쩌면이 이상한 시간

했다

멋진 밤이었다 못생긴 밤 어쩌면

입니다

을 :

나는 스크립트는 다음과 같이 sententes을 구축 할 수 있어야 의미

기타 등등 ...

char에 의해 char이라는 문자열을 읽고 나중에 계산을 위해 괄호 값을 저장하는 스택이있는 상태 머신을 bulid해야하나요?

그런 목적을위한 바로 사용할 수있는 라이브러리일까요?

답변

8

시도 Treetop. 문법을 설명하는 Ruby와 유사한 DSL입니다. 당신이 제공 한 문자열을 파싱하는 것은 아주 쉬워야하며, 실제 파서를 사용하면 나중에 쉽게 문법을 확장 할 수 있습니다.

파싱 할 문자열의 유형에 대한 예 문법 (sentences.treetop로 저장) :

grammar Sentences 
    rule sentence 
    # A sentence is a combination of one or more expressions. 
    expression* <Sentence> 
    end 

    rule expression 
    # An expression is either a literal or a parenthesised expression. 
    parenthesised/literal 
    end 

    rule parenthesised 
    # A parenthesised expression contains one or more sentences. 
    "(" (multiple/sentence) ")" <Parenthesised> 
    end 

    rule multiple 
    # Multiple sentences are delimited by a pipe. 
    sentence "|" (multiple/sentence) <Multiple> 
    end 

    rule literal 
    # A literal string contains of word characters (a-z) and/or spaces. 
    # Expand the character class to allow other characters too. 
    [a-zA-Z ]+ <Literal> 
    end 
end 

문법 위에서 우리가 노드 값에 액세스 할 수 있도록 클래스를 정의하는 첨부 파일이 필요합니다 (sentence_nodes.rb으로 저장).

class Sentence < Treetop::Runtime::SyntaxNode 
    def combine(a, b) 
    return b if a.empty? 
    a.inject([]) do |values, val_a| 
     values + b.collect { |val_b| val_a + val_b } 
    end 
    end 

    def values 
    elements.inject([]) do |values, element| 
     combine(values, element.values) 
    end 
    end 
end 

class Parenthesised < Treetop::Runtime::SyntaxNode 
    def values 
    elements[1].values 
    end 
end 

class Multiple < Treetop::Runtime::SyntaxNode 
    def values 
    elements[0].values + elements[2].values 
    end 
end 

class Literal < Treetop::Runtime::SyntaxNode 
    def values 
    [text_value] 
    end 
end 

다음 예제 프로그램

은 당신이 준 예제 문장을 분석하는 것은 매우 간단 보여줍니다.

require "rubygems" 
require "treetop" 
require "sentence_nodes" 

str = 'maybe (this is|that was) some' + 
    ' ((nice|ugly) (day|night)|(strange (weather|time)))' 

Treetop.load "sentences" 
if sentence = SentencesParser.new.parse(str) 
    puts sentence.values 
else 
    puts "Parse error" 
end 

이 프로그램의 출력은 다음과 같습니다

maybe this is some nice day 
maybe this is some nice night 
maybe this is some ugly day 
maybe this is some ugly night 
maybe this is some strange weather 
maybe this is some strange time 
maybe that was some nice day 
maybe that was some nice night 
maybe that was some ugly day 
maybe that was some ugly night 
maybe that was some strange weather 
maybe that was some strange time 

또한 구문 트리에 액세스 할 수 있습니다

p sentence 

The output is here.

당신은 그것을 가지고 있습니다 : 약 50 줄의 코드에서 당신이하고 싶은 것과 아주 가깝게 만들어야하는 확장 가능한 파싱 솔루션입니다. 그게 도움이 되니?

+0

감사합니다. 인터넷에서 예제를 읽었지 만 중첩 된 괄호를 읽는 방법을 이해하지 못했습니다 ... – astropanic

+0

Thanks Man! 너는 내 영웅이야. – astropanic

+0

http://www.bestechvideos.com/2008/07/18/rubyconf-2007-treetop-syntactic-analysis-with-ruby, 좋은 비디오 – astropanic