Вот еще один способ ее решения (по крайней мере, пример, который вы разместили).
Итак, вы хотите заменить ...function(1)
на ...extraFunction();\nfunction(1)
, где точки - это отступы, а \n
- разрыв строки.
То, что вы можете сделать, это совпадение:
Function1
: Spaces 'function' Spaces '(' Spaces '1' Spaces ')'
;
fragment Spaces
: (' ' | '\t')*
;
и замените его на соответствующий текст, но предварительно добавив дополнительный метод. Тем не менее, лексер теперь будет жаловаться, когда он натыкается на ввод, как:
'function()'
(без параметра 1 в качестве параметра)
или
' x...'
(отступы не , за которыми следуют f из функция )
Итак, вам нужно "разветвляться" в своем правиле Function1
и убедиться, что вы заменяете только правильное вхождение.
Вы также должны позаботиться о вхождениях function(1)
внутри строковых литералов и комментариев, предполагая, что вы не хотите, чтобы они были предварительно добавлены с extraFunction();\n
.
Небольшая демонстрация:
grammar T;
parse
: (t=. {System.out.print($t.text);})* EOF
;
Function1
: indent=Spaces
( 'function' Spaces '(' Spaces ( '1' Spaces ')' {setText($indent.text + "extraFunction();\n" + $text);}
| ~'1' // do nothing if something other than `1` occurs
)
| '"' ~('"' | '\r' | '\n')* '"' // do nothing in case of a string literal
| '/*' .* '*/' // do nothing in case of a multi-line comment
| '//' ~('\r' | '\n')* // do nothing in case of a single-line comment
| ~'f' // do nothing in case of a char other than 'f' is seen
)
;
OtherChar
: . // a "fall-through" rule: it will match anything if none of the above matched
;
fragment Spaces
: (' ' | '\t')* // fragment rules are only used inside other lexer rules
;
Вы можете проверить это с помощью следующего класса:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source =
"/* \n" +
" function(1) \n" +
"*/ \n" +
"void myFunction() { \n" +
" s = \"function(1)\"; \n" +
" function(); \n" +
" function(1); \n" +
"} \n";
System.out.println(source);
System.out.println("---------------------------------");
TLexer lexer = new TLexer(new ANTLRStringStream(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.parse();
}
}
И если вы запустите этот основной класс, вы увидите следующее, выводимое на консоль:
bart@hades:~/Programming/ANTLR/Demos/T$ java -cp antlr-3.3.jar org.antlr.Tool T.g
bart@hades:~/Programming/ANTLR/Demos/T$ javac -cp antlr-3.3.jar *.java
bart@hades:~/Programming/ANTLR/Demos/T$ java -cp .:antlr-3.3.jar Main
/*
function(1)
*/
void myFunction() {
s = "function(1)";
function();
function(1);
}
---------------------------------
/*
function(1)
*/
void myFunction() {
s = "function(1)";
function();
extraFunction();
function(1);
}
Я уверен, что это не защищает от ошибок (например, я не учел букв-символов), но это может стать началом, IMO.