Вы используете getChild(1)
для доступа к аргументу оператора печати. Это даст вам TerminalNode
, содержащий токен ID
или STRLIT
. Вы можете получить доступ к токену с помощью метода getSymbol()
, а затем получить доступ к типу токена с помощью свойства .type
. Типом будет число, которое вы можете сравнить с такими константами, как MyLanguageParser.ID
или MyLanaguageParser.STRLIT
.
Использование getChild
не обязательно является лучшим способом доступа к дочерним узлам узла. Каждый контекстный класс будет иметь определенные c средства доступа для каждого из его дочерних элементов.
В частности, у объекта PrintContext
будут методы ID()
и STRLIT()
. Один из них вернет null
, другой вернет TerminalNode
объект, содержащий данный токен. Таким образом, вы знаете, был ли это идентификатор или строковый литерал, увидев, какой из них не равен нулю.
Тем не менее, более распространенным решением будет отсутствие объединения возможных типов аргументов в print
правило, но вместо этого разрешите любое выражение в качестве аргумента print
. Затем вы можете использовать помеченные альтернативы в своем правиле expression
, чтобы получить разные методы посетителя для каждого вида выражения:
print : PRINTKW expression NEWLINE;
expression
: STRLIT #StringLiteral
| ID #Variable
;
Тогда ваш посетитель может выглядеть следующим образом:
myVisitor.prototype.visitPrint = function(ctx) {
const arg = this.visit(ctx.expression());
const Js = `console.log(${arg});`;
// write to file
fs.writeFile(targetFs + fileName + '.js', Js, 'utf8', function (err) {
if (err) return console.log(err);
console.log(`done`);
});
};
myVisitor.prototype.visitStringLiteral = function(ctx) {
const text = ctx.getText();
return `"${text.substring(1, text.length - 1)}"`;
}
myVisitor.prototype.visitVariable = function(ctx) {
return ctx.getText();
}
В качестве альтернативы Вы могли бы опустить метки и вместо этого определить метод visitExpression
, который обрабатывает оба случая, посмотрев, какой метод получения возвращает значение null:
myVisitor.prototype.visitExpression = function(ctx) {
if (ctx.STRLIT !== null) {
const text = ctx.getText();
return `"${text.substring(1, text.length - 1)}"`;
} else {
return ctx.getText();
}
}
PS: обратите внимание, что одинарные кавычки прекрасно работают в JavaScript, поэтому вам на самом деле не нужно разбирать одинарные кавычки и заменять их двойными кавычками. Вы можете просто использовать .getText()
без какой-либо последующей обработки в обоих случаях, и это все равно будет иметь значение JavaScript.