Probar Treetop. Es un DSL similar a Ruby para describir gramáticas. Analizar el hilo que has dado debería ser bastante fácil, y al usar un analizador real podrás extender tu gramática más tarde.
una gramática ejemplo para el tipo de cadena que se desea analizar (guardar como 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
La gramática anterior necesita un archivo adjunto que define las clases que nos permiten acceder a los valores de los nodos (guardar como 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
El siguiente programa de ejemplo muestra que es bastante simple analizar la oración de ejemplo que ha dado.
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
La salida de este programa es:
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
También puede acceder al árbol de sintaxis:
p sentence
The output is here.
Ahí lo tienes: una solución de análisis escalable que debería acercarse bastante a lo que quieres hacer en aproximadamente 50 líneas de código. ¿Eso ayuda?
Gracias, he leído los ejemplos en la red, pero no entiendo cómo puedo leer paréntesis anidados ... – astropanic
¡Gracias, amigo! Eres mi héroe :) – astropanic
http://www.bestechvideos.com/2008/07/18/rubyconf-2007-treetop-syntactic-analysis-with-ruby, buen video – astropanic