Ваш ввод:
InfoFromDb: 0xF8, FooData 3
ID from database: 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1
маркируется следующим образом:
INFO -> `InfoFromDb`
INFO_INTERMEDIATE -> `: `
INFO_DATA -> `0xF8, FooData 3`
INFO_END -> `\n`
ID -> `ID from database`
ID_DATA -> `: 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1`
независимо от правил синтаксического анализатора, которые вы вызываете. Лексер всегда применяет следующие правила:
- соответствует максимально возможному количеству символов
- в случае, если 2 (или более) правила лексера соответствуют одинаковому количеству символов, правило, определенное первым " wins "
РЕДАКТИРОВАТЬ
почему ID_INTERMEDIATE не распознается? Он упорядочен правильно (ваш случай № 2). Есть ли способ заставить токены быть необязательными?
Нет, ID_INTERMEDIATE
не соответствует, потому что ID_DATA
соответствует большему количеству (правило 1 применимо здесь). Лексер смотрит на правило 2 только тогда, когда 2 правила совпадают с одинаковыми символами (это не так, ID_INTERMEDIATE
соответствует ": "
и ID_DATA
соответствует ": 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1"
)
, если я добавлю общее правило нового синтаксического анализатора: (the_id | info) * EOF; и проверьте это ... the_id не показывает ошибку ... но он все еще не анализирует промежуточный токен
Я не совсем понимаю, что вы имеете в виду. Если я посмотрю на ваше правило синтаксического анализатора the_id: ID ID_DATA;
, то оно не выдаст ошибку, потому что нет ID_INTERMEDIATE
. выдает ошибку, когда вы делаете: the_id: ID ID_INTERMEDIATE ID_DATA;
Я понимаю, что ~ [\ r \ n] + соответствует большему количеству символов ... но мне нужно пропустить / Откажитесь от: потому что я не хочу соответствовать всей правой части этой входной строки
Тогда вам нужно сделать ID_DATA
менее жадным, чем сейчас. Может быть, не давайте начать с :
?