Как определить правило по умолчанию в 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_, он бы понял, что нет постоянной.

Обратите внимание, что вы также хотите, чтобы правило соответствовало пустым строкам, поэтому пустые строки не являются синтаксическими ошибками.

Другие вопросы по тегам