Анализ SGF на вершине дерева
Вопрос
В настоящее время я пытаюсь написать грамматику Treetop для анализа файлов простого формата игры, и пока она в основном работает.Однако возникло несколько вопросов.
- Я не уверен, как на самом деле получить доступ к структуре, которую Treetop генерирует после анализа.
- Есть ли лучший способ захвата всех персонажей, чем правило моих символов?
Есть случай для комментариев, которые я не могу написать правильно.
C[player1[4k\]:привет игрок2 [3k\]:привет!]
Я не могу понять, как обращаться с вложенной структурой узла C[] с [] внутри них.
Ниже приводится мой текущий прогресс.
sgf-grammar.treetop
grammar SgfGrammar
rule node
'(' chunk* ')' {
def value
text_value
end
}
end
rule chunk
';' property_set* {
def value
text_value
end
}
end
rule property_set
property ('[' property_data ']')* / property '[' property_data ']' {
def value
text_value
end
}
end
rule property_data
chars '[' (!'\]' . )* '\]' chars / chars / empty {
def value
text_value
end
}
end
rule property
[A-Z]+ / [A-Z] {
def value
text_value
end
}
end
rule chars
[a-zA-Z0-9_/\-:;|'"\\<>(){}!@#$%^&\*\+\-,\.\?!= \r\n\t]*
end
rule empty
''
end
end
И мой тестовый пример, в настоящее время исключающий узлы C[] с вышеупомянутой проблемой вложенных скобок:
пример.rb
require 'rubygems'
require 'treetop'
require 'sgf-grammar'
parser = SgfGrammarParser.new
parser.parse("(;GM[1]FF[4]CA[UTF-8]AP[CGoban:3]ST[2]
RU[Japanese]SZ[19]KM[0.50]TM[1800]OT[5x30 byo-yomi]
PW[stoic]PB[bojo]WR[3k]BR[4k]DT[2008-11-30]RE[B+2.50])")
Решение
- Структура возвращается к вам в виде дерева SyntaxNodes (если результат равен нулю, проверьте parser.failure_reason).Вы можете пройтись по этому дереву или (и это рекомендуется) дополнить его функциями, которые делают то, что вы хотите, и просто вызвать свою основную функцию в корне.
Если вы имеете в виду "как вы получаете доступ к компонентам из функции узла?" Есть несколько способов.Вы можете получить их с помощью нотации element[x] или по правилу:
rule url_prefix
protocol "://" host_name {
def example
assert element[0] == protocol
assert element[2] == host_name
unless protocol.text_value == "http"
print "#{protocol.text_value} not supported"
end
end
}
Вы также можете назвать их так:
rule phone_number
"(" area_code:( digit digit digit ) ")" ...
а затем обратитесь к ним по имени.
Ваше правило символов выглядит нормально, если вы хотите сопоставить только эти символы.Если вы хотите соответствовать любой символ, вы можете просто использовать точку (.), как в регулярном выражении.
Я не знаком с языком, который вы пытаетесь проанализировать, но правило, которое вы ищете, может быть примерно таким:
rule comment "C" balanced_square_bracket_string end rule balanced_square_bracket_string "[" ( [^\[\]] / balanced_square_bracket_string )* "]" end
Средняя часть второго правила соответствует всему, что не является квадратной скобкой или вложенной строкой с сбалансированными квадратными скобками.
P.S.Существует довольно активная группа Google, с онлайн-архивами и возможностью поиска.