Как определить правило по умолчанию в EBNF/Tatsu?
У меня есть проблема в моей реализации EBNF и Tatsu извлечь грамматику EBNF для Tatsu:
define ='#define' constantename [constante] ;
constante = CONSTANTE ;
CONSTANTE = ( Any | ``true`` ) ;
Any = /.*/ ;
constantename = (/[A-Z0-9_()]*/) ;
Когда я проверяю с:
#define _TEST01_ "test01"
#define _TEST_
#define _TEST02_ "test02"
Я получил:
[
"#define",
"_TEST01_",
"\"test01\""
],
[
"#define",
"_TEST_",
"#define _TEST02_ \"test02\""
]
Но я хочу этого:
[
"#define",
"_TEST01_",
"\"test01\""
],
[
"#define",
"_TEST_",
"true"
],
[
"#define",
"_TEST02_",
"\"test02\""
]
Где моя ошибка?
Большое спасибо...
1 ответ
Проблема в том, что Тацу по умолчанию пропускает пробелы, включая переводы строк, между элементами. Поэтому, когда вы применяете правило '#define' constantename [constante]
на вход:
#define _TEST_
#define _TEST02_ "test02"
Это первые совпадения #define
с '#define'
, затем пропускает пробел, затем соответствует _TEST_
с constantename
, затем пропускает новую строку, а затем совпадает #define _TEST02_ "test02"
с ANY
(с помощью constante
).
Обратите внимание, что это именно то поведение, которое вы хотели бы (я предполагаю), если бы не было новой строки:
#define _TEST_ #define _TEST02_ "test02"
Здесь вы хотели бы вывод ["#define", "_TEST_", "#define _TEST02_ \"test02\""]
, право? По крайней мере, препроцессор C будет обрабатывать это так же, как в этом случае.
Так что это говорит нам о том, что перевод строки является значительным. Поэтому вы не можете игнорировать это. Вы можете сказать Тацу игнорировать только символы табуляции и пробелы (не переводы строк), либо передавая whitespace = '\t '
как вариант при создании парсера или путем добавления этой строки в грамматику:
@@whitespace :: /[\t ]+/
Теперь вам нужно будет явно указывать новые строки везде, где должны идти новые строки, поэтому ваше правило становится следующим:
define ='#define' constantename [constante] '\n';
Теперь ясно, что константа, если она присутствует, должна появляться до разрыва строки, поэтому для строки #define _TEST_
, он бы понял, что нет постоянной.
Обратите внимание, что вы также хотите, чтобы правило соответствовало пустым строкам, поэтому пустые строки не являются синтаксическими ошибками.