Как определить правило по умолчанию в EBNF / Tatsu? - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть проблема в моей реализации EBNF и Tatsu Извлечение грамматики EBNF для Тацу:

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 Ответ

0 голосов
/ 08 ноября 2018

Проблема в том, что Тацу по умолчанию пропускает пробелы, включая переводы строк, между элементами. Поэтому, когда вы применяете правило '#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 будет обрабатывать его так же, как в этом случае.

Итак, это говорит нам о том, что перевод строки является значительным. Поэтому вы не можете игнорировать это. Вы можете сказать Tatsu игнорировать только символы табуляции и пробелы (не переводы строк), передавая whitespace = '\t ' в качестве опции при создании парсера или добавив эту строку в грамматику:

@@whitespace :: /[\t ]+/

Теперь вам нужно будет явно указывать новые строки везде, где должны идти новые строки, поэтому ваше правило становится:

define  ='#define' constantename [constante] '\n';

Теперь ясно, что константа, если она присутствует, должна появиться до разрыва строки, поэтому для строки #define _TEST_ будет понятно, что константы нет.

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

...