Текущее поведение: 2 * 5 + SUM(1, 2, 3)
[
"2",
"*",
"5",
"+",
"SUM",
"(",
[
"1",
",",
"2",
",",
"3"
],
")"
]
Желаемое поведение : 2 * 5 + SUM(1, 2, 3)
[
"2",
" ",
"*",
" ",
"5",
" ",
"+",
" ",
"SUM",
"(",
[
"1",
",",
" ",
"2",
",",
" ",
"3"
],
")"
]
Грамматика для копирования: https://pastebin.com/zpwqT6Uw
Площадка PEG.js https://pegjs.org/online
Что мне не хватает?
@futagoza невероятно жаль вас беспокоить, но я впервые имею дело с PEG.js, и эта проблема для меня критична. Могу я попросить вас о небольшой подсказке?
С уважением,
Марек
Я пытался просмотреть вашу грамматику (вчера и только что), но, поскольку ее действительно сложно понять (не говоря уже о соглашениях об именах, формат, если честно, повсюду), мне потребовалось некоторое время, чтобы найти решение:
const
возвращает [left_space, cnst, right_space]
)[].concat.apply([], con)
Тем не менее, если быть честным с вами, это кажется мне хакерским решением. У вас есть ссылка на спецификацию или что-то в этом роде? Было бы полезно узнать, какие правила я могу и не могу изменить, чтобы получить желаемый результат без вышеуказанного хакерского решения.
Если нет, если вы готовы потратить время и привести в порядок грамматику и переименовать некоторые правила (чтобы было легче понять, что вы хотите), то я с удовольствием попробую еще раз 😉
@marek-baranowski - Извините, я не видел этого до сих пор. Надеюсь, это все еще полезно для вас
Если вы хотите сохранить пробелы, просто относитесь к ним как к сопоставляемому содержимому.
Не совсем понятно, что именно вы хотите для двух пространств. У вас может быть либо строка из двух пробелов, либо массив из двух строк с одним пробелом. Обычно я ожидаю первого, но... все, что вам нужно, это посимвольно
Кроме того... зачем вам такие случайные символы, кроме вызова функции? Парсер должен суммировать их для вас.
В любом случае
Это то, что вы просили:
Document = Expression*
Whitespace
= tx:[ \r\n]+ { return tx.join(''); }
Number
= str:[0-9]+ { return str.join(''); }
Oper
= '+'
/ '-'
/ '/'
/ '*'
/ ','
Label
= l:[a-zA-Z]+ { return l.join(''); }
Parens
= '(' Whitespace? ex:Expression* Whitespace? ')' { return ex; }
Expression
= Number
/ Oper
/ Whitespace
/ Label
/ Parens
/ [^()]+
Дело в том, что я не очень уверен, что это на самом деле то, что вы хотите. В качестве примера вместо этого вы можете проанализировать числа и операторы и вернуть стандартную форму узла для каждого из них:
Document = Expression*
Whitespace
= tx:[ \r\n]+ { return {
ast: 'whitespace', value: tx.join('')
}; }
Number
= str:[0-9]+ { return {
ast: 'number', value: parseInt(str,10)
}; }
Oper
= '+' { return { ast: 'oper', value: 'add' }}
/ '-' { return { ast: 'oper', value: 'subtract' }}
/ '/' { return { ast: 'oper', value: 'divide' }}
/ '*' { return { ast: 'oper', value: 'multiply' }}
/ ',' { return { ast: 'oper', value: 'sequence' }}
Label
= l:[a-zA-Z]+ { return {
ast: 'label', value: l.join('')
}; }
Parens
= '(' Whitespace? ex:Expression* Whitespace? ')' {
return { ast: 'parens', value: ex
}; }
Expression
= Number
/ Oper
/ Whitespace
/ Label
/ Parens
/ [^()]+
Теперь у вас все еще есть пробелы, но у вас также есть правильно проанализированное дерево, и вам не нужно писать синтаксический анализатор для синтаксического анализа вывода вашего синтаксического анализатора, и теперь также очень просто начать добавлять регуляризованные функции, такие как номера строк и т. д.
@marek-baranowski - я бы хотел немного уменьшить размер этого трекера
Если это то, что вам нужно, не могли бы вы закрыть этот вопрос? Спасибо 😄
Если это не так, дайте мне знать, почему, и я попробую еще раз
@marek-baranowski Еще один нежный пинг :smiley_cat:
Кроме того, я написал плагин pegjs-syntactic-actions для PEG.js, чтобы облегчить отладку грамматик и, в частности, посмотреть, какие символы захватываются каким правилом независимо от действий, что, вероятно, является вашей проблемой здесь, как объяснил @StoneCypher.
Обоснование этого плагина таково: мне часто/иногда трудно понять глобальный результат, когда он не соответствует нашим ожиданиям, потому что он является результатом комбинации множества мелких действий, и поиск действия, которое ведет себя плохо/странно, может быть кропотливый. С помощью этого плагина мы видим, какое правило захватывает какой символ, и он дает имя действия, над которым нужно действовать.
ух ты, это действительно опрятно на самом деле
Самый полезный комментарий
@marek-baranowski Еще один нежный пинг :smiley_cat:
Кроме того, я написал плагин pegjs-syntactic-actions для PEG.js, чтобы облегчить отладку грамматик и, в частности, посмотреть, какие символы захватываются каким правилом независимо от действий, что, вероятно, является вашей проблемой здесь, как объяснил @StoneCypher.
Обоснование этого плагина таково: мне часто/иногда трудно понять глобальный результат, когда он не соответствует нашим ожиданиям, потому что он является результатом комбинации множества мелких действий, и поиск действия, которое ведет себя плохо/странно, может быть кропотливый. С помощью этого плагина мы видим, какое правило захватывает какой символ, и он дает имя действия, над которым нужно действовать.