Я предполагаю, что ваша реальная проблема немного сложнее, потому что, если "023abc7defghij"
- ваш фактический ввод, я бы не использовал генератор синтаксического анализатора, такой как ANTLR, а просто придерживался некоторых простых строковых операций.
Тем не менее, вот возможное решение:
Поскольку ваши chunks
не известны заранее, вы не можете создать никаких токенов, кроме одного Digit
и Other
токена, который был бы любымсимвол, отличный от цифры.Обратите внимание, что вам на самом деле не нужна информация header
: вы просто анализируете "3"
и затем получаете следующие 3 символа, затем анализируете "7"
и получаете следующие 7 символов, ... вплоть доконец файла.
Грамматика для такого языка может выглядеть следующим образом:
grammar T;
parse
: file EOF
;
file
: header chunk*
;
header
: Digit Digit
;
chunk
: Digit any*
;
any
: Digit
| Other
;
Digit
: '0'..'9'
;
Other
: .
;
Но теперь правило chunk
неоднозначно: теперь нет необходимости останавливать потребление символов,Это может быть сделано с использованием стробированного семантического предиката , который заставит *
из any*
перестать потреблять, когда определенное условие выполнено (когда счетчик int n
имеетв данном случае это был обратный отсчет).
Приведенная выше грамматика, включающая этот предикат и некоторые println
-отношения, будет выглядеть так:
grammar T;
parse
: file EOF
;
file
: header {System.out.println("header=" + $header.text);}
(chunk {System.out.println("chunk=" + $chunk.text);})*
;
header
: Digit Digit
;
chunk
: Digit {int n = Integer.valueOf($Digit.text);} ({n > 0}?=> any {n--;})*
;
any
: Digit
| Other
;
Digit
: '0'..'9'
;
Other
: .
;
, которую можно протестировать с помощью класса:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "023abc7defghij";
TLexer lexer = new TLexer(new ANTLRStringStream(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.parse();
}
}
Если вы сейчас сгенерируете лексер и парсер, скомпилируйте весь файл .java
и запустите класс Main
:
java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main
, вы увидите, что на вашем принтере будет напечатано следующееконсоль:
header=02
chunk=3abc
chunk=7defghij