blob: f204e4817c1d6e7512837932825caa7deeefb3c4 [file] [log] [blame]
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.template.impl;
import com.google.common.annotations.VisibleForTesting;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.Macro;
import com.intellij.codeInsight.template.macro.MacroFactory;
import com.intellij.lexer.Lexer;
import com.intellij.psi.tree.IElementType;
@VisibleForTesting
public class MacroParser {
//-----------------------------------------------------------------------------------
public static Expression parse(String expression) {
if (expression.length() == 0) {
return new ConstantNode("");
}
Lexer lexer = new MacroLexer();
lexer.start(expression);
skipWhitespaces(lexer);
return parseMacro(lexer, expression);
}
//-----------------------------------------------------------------------------------
private static void advance(Lexer lexer) {
lexer.advance();
skipWhitespaces(lexer);
}
//-----------------------------------------------------------------------------------
private static void skipWhitespaces(Lexer lexer) {
while (lexer.getTokenType() == MacroTokenType.WHITE_SPACE) {
lexer.advance();
}
}
//-----------------------------------------------------------------------------------
private static String getString(Lexer lexer, String expression) {
return expression.substring(lexer.getTokenStart(), lexer.getTokenEnd());
}
//-----------------------------------------------------------------------------------
@SuppressWarnings({"HardCodedStringLiteral"})
private static Expression parseMacro(Lexer lexer, String expression) {
IElementType tokenType = lexer.getTokenType();
String token = getString(lexer, expression);
if (tokenType == MacroTokenType.STRING_LITERAL) {
advance(lexer);
return new ConstantNode(token.substring(1, token.length() - 1).replaceAll("\\\\n", "\n").
replaceAll("\\\\r", "\r").replaceAll("\\\\t", "\t").replaceAll("\\\\f", "\f").replaceAll("\\\\(.)", "$1"));
}
if (tokenType != MacroTokenType.IDENTIFIER) {
System.out.println("Bad macro syntax: Not identifier: " + token);
advance(lexer);
return new ConstantNode("");
}
Macro macro = MacroFactory.createMacro(token);
if (macro == null) {
return parseVariable(lexer, expression);
}
advance(lexer);
MacroCallNode macroCallNode = new MacroCallNode(macro);
if (lexer.getTokenType() == null) {
return macroCallNode;
}
if (lexer.getTokenType() != MacroTokenType.LPAREN) {
return macroCallNode;
}
advance(lexer);
parseParameters(macroCallNode, lexer, expression);
if (lexer.getTokenType() != MacroTokenType.RPAREN) {
System.out.println("Bad macro syntax: ) expected: " + expression);
}
advance(lexer);
return macroCallNode;
}
private static void parseParameters(MacroCallNode macroCallNode, Lexer lexer, String expression) {
if (lexer.getTokenType() != MacroTokenType.RPAREN) {
while (lexer.getTokenType() != null) {
Expression node = parseMacro(lexer, expression);
macroCallNode.addParameter(node);
if (lexer.getTokenType() == MacroTokenType.COMMA) {
advance(lexer);
}
else {
break;
}
}
}
}
private static Expression parseVariable(Lexer lexer, String expression) {
String variableName = getString(lexer, expression);
advance(lexer);
if (lexer.getTokenType() == null) {
if (TemplateImpl.END.equals(variableName)) {
return new EmptyNode();
}
return new VariableNode(variableName, null);
}
if (lexer.getTokenType() != MacroTokenType.EQ) {
return new VariableNode(variableName, null);
}
advance(lexer);
Expression node = parseMacro(lexer, expression);
return new VariableNode(variableName, node);
}
}