Как сгруппировать непустые строки с PEG.js
Я пытаюсь проанализировать файл категорий с PEG.js
Как я могу сгруппировать категории (набор непустых строк, за которыми следует пустая строка)
stopwords:fr:aux,au,de,le,du,la,a,et,avec
synonyms:en:flavoured, flavored
synonyms:en:sorbets, sherbets
en:Artisan products
fr:Produits artisanaux
< en:Artisan products
fr:Gressins artisanaux
en:Baby foods
fr:Aliments pour bébé, aliment pour bébé, alimentation pour bébé, aliment bébé, alimentation bébé, aliments bébé
< en:Baby foods
fr:Céréales pour bébé, céréales bébé
< en:Whisky
fr:Whisky écossais
es:Whiskies escoceses
wikipediacategory:Q8718387
Сейчас я могу анализировать построчно этот код:
start = stopwords* synonyms* category+
language_and_words = l:[^:]+ ":" w:[^\n]+ {return {language: l.join(''), words: w.join('')};}
stopwords = "stopwords:" w:language_and_words "\n"+ {return {stopwords: w};}
synonyms = "synonyms:" w:language_and_words "\n"+ {return {synonyms: w};}
category_line = "< "? w:language_and_words "\n"+ {return w;}
category = c:category_line+ {return c;}
Я получил:
{
"language": "en",
"words": "Artisan products"
},
{
"language": "fr",
"words": "Produits artisanaux"
}
но я хочу (для каждой группы):
{
{
"language": "en",
"words": "Artisan products"
},
{
"language": "fr",
"words": "Produits artisanaux"
}
}
Я тоже это попробовал, но он не группировался, и я получил \n в начале некоторых строк.
category_line = "< "? w:language_and_words "\n" {return w;}
category = c:category_line+ "\n" {return c;}
2 ответа
Я нашел частичное решение:
start = category+
word = c:[^,\n]+ {return c.join('');}
words = w:word [,]? {return w.trim();}
parent = p:"< "? {return (p !== null);}
line = p:parent w:words+ "\n" {return {parent: p, words: w};}
category = l:line+ "\n"? {return l;}
Я могу разобрать это...
< fr:a,b
fr:aa,bb
en:d,e,f
fr:dd,ee, ffff
и сгруппировать:
[
[ {...}, {...} ],
[ {...}, {...} ]
]
Но есть проблема с "lang:" в начале каждой категории, если я пытаюсь разобрать "lang:" мои категории не сгруппированы...
Я считаю, что полезно итеративно разбивать синтаксический анализ (декомпозиция проблемы, old-school a la Wirth). Вот частичное решение, которое, я думаю, направит вас в правильном направлении (я не разбирал Line
элементы категорий.
start =
stopwords
synonyms
category+
category "category"
= category:(Line)+ categorySeparator { return category }
stopwords "stopwords"
= stopwordLine*
stopwordLine "stopword line"
= stopwordLine:StopWordMatch EndOfLine* { return stopwordLine }
StopWordMatch
= "stopwords:" match:Text { return match }
synonyms "stopwords"
= synonymLine*
synonymLine "stopword line"
= synonymLine:SynonymMatch EndOfLine* { return synonymLine }
SynonymMatch
= "synonyms:" match:Text { return match }
Line "line"
= line:Text [\n] { return line }
Text "text"
= [^\n]+ { return text() }
EndOfLine "(end of line)"
= '\n'
EndOfFile
= !. { return "EOF"; }
categorySeparator "separator"
= EndOfLine EndOfLine* / EndOfLine? EndOfFile
Я использую смешанный случай произвольно и не очень стильно. Есть также способ сохранить решения в Интернете: http://peg.arcanis.fr/2WQ7CZ/