Поэтому, когда я ввожу «abc», парсер печатает «a», «b», а затем убогий ASCII 10. Затем я набираю «1 2 3 4», и только потом парсер печатает «c» и т. Д.Я на Linux / Java 9.
Этого следовало ожидать.Ваш анализатор печатает только семантические значения sim
символов и только тогда, когда он уменьшает их до inp
.Он не будет выполнять такое уменьшение без маркера предварительного просмотра, несмотря на тот факт, что в вашем конкретном синтаксическом анализаторе выбор всегда должен уменьшаться, когда символ в конце очереди равен sim
.Но ваш лексер печатает сообщение новой строки, как только сканируется новая строка в процессе получения такого токена предварительного просмотра, до сокращения, которое приводит к печати предыдущего семантического значения.
Если переводы строки значимы для вашей грамматики , тогда ваш лексер должен испускать для них токены, а не работать с ними напрямую, и ваша грамматика должна учитывать эти токены.Например:
inp : line { System.out.print($1); }
| inp NL line { System.out.println("NEWLINE WAS HERE"); System.out.print($3); }
;
line : /* empty */ { $$ = new StringBuilder(); }
| line sim { $$ = $1.append($2).append('\n'); }
;
sim : ID
| NUM
;
Предполагается, что лексер выдает NL
токен вместо , распечатывающего сообщение.Обратите внимание, что вся печать в этом примере происходит на одном уровне.Если печать - это то, что вы действительно хотите сделать, то выполнение всего этого на одном уровне облегчает намного контроль и прогнозирование порядка, в котором будут печататься вещи.
Примечание: этот парсер немного быстрый и грязный, содержит конфликт сдвиг / уменьшение.По умолчанию разрешение сдвига является правильным.Конфликт оказывается сложным для правильной сортировки, если только вы не заставите свой лексер вставить синтетический токен NL в конце ввода.Кроме того, вам, конечно, необходимо установить правильный тип токена для символа line
.
С другой стороны , если переводы строки не значимык грамматике, то вы должны полностью игнорировать их.В этом случае ваша проблема вообще не возникает.