/* * Copyright 2000-2013 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.coldFusion.model.parsers; import com.intellij.coldFusion.CfmlBundle; import com.intellij.coldFusion.model.CfmlUtil; import com.intellij.coldFusion.model.lexer.CfmlTokenTypes; import com.intellij.coldFusion.model.psi.stubs.CfmlStubElementTypes; import com.intellij.lang.PsiBuilder; import com.intellij.psi.tree.IElementType; import static com.intellij.coldFusion.model.lexer.CfscriptTokenTypes.*; /** * Created by Lera Nikolaenko * Date: 13.01.2009 */ public class CfscriptParser { // parse statement or statements block in curly brackets // if no curly brackets than parse only one statement private static void parseExpression(PsiBuilder myBuilder) { (new CfmlExpressionParser(myBuilder)).parseExpression(); } private static void parseRValue(PsiBuilder myBuilder) { (new CfmlExpressionParser(myBuilder)).parseRValue(); } private static boolean parseOptionalIDAndTags_PropertyUtil(PsiBuilder myBuilder) { PsiBuilder.Marker propertyBodyMarker = myBuilder.mark(); // parse Type ID attributes // parse ID attributes // parse attributes if (myBuilder.getTokenType() == IDENTIFIER) { myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { propertyBodyMarker.rollbackTo(); CfmlParser.parseAttributes(myBuilder, "cfproperty", IDENTIFIER, true); return true; } else if (myBuilder.getTokenType() == IDENTIFIER) { PsiBuilder.Marker attributesMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { attributesMarker.rollbackTo(); propertyBodyMarker.drop(); CfmlParser.parseAttributes(myBuilder, "cfproperty", IDENTIFIER, true); return true; } else { attributesMarker.drop(); propertyBodyMarker.rollbackTo(); return false; } } //try to parse type in "property type name;" expression// else if (myBuilder.getTokenType() == POINT) { if (!parseType(myBuilder) || myBuilder.getTokenType() != IDENTIFIER) { propertyBodyMarker.rollbackTo(); return false; } } else if (myBuilder.getTokenType() == SEMICOLON) { propertyBodyMarker.drop(); return true; } } propertyBodyMarker.drop(); return false; } private boolean parseProperty(PsiBuilder myBuilder) { assert myBuilder.getTokenType() == IDENTIFIER; PsiBuilder.Marker propertyMarker = myBuilder.mark(); myBuilder.advanceLexer(); // parse Type ID attributes // parse ID attributes // parse attributes if (!parseOptionalIDAndTags_PropertyUtil(myBuilder)) { if (!parseType(myBuilder)) { propertyMarker.drop(); return false; } if (!parseOptionalIDAndTags_PropertyUtil(myBuilder)) { propertyMarker.drop(); return false; } else { propertyMarker.done(CfmlElementTypes.PROPERTY); return true; } } else { propertyMarker.done(CfmlElementTypes.PROPERTY); return true; } } private void parseAction(PsiBuilder myBuilder) { // http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec0999c-7ffa.html assert myBuilder.getTokenType() == IDENTIFIER; final String actionName = myBuilder.getTokenText(); PsiBuilder.Marker actionMarker = myBuilder.mark(); myBuilder.remapCurrentToken(ACTION_NAME); myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { actionMarker.rollbackTo(); myBuilder.remapCurrentToken(IDENTIFIER); (new CfmlExpressionParser(myBuilder)).parseStatement(); eatSemicolon(myBuilder); } else { CfmlParser.parseAttributes(myBuilder, "cfproperty", IDENTIFIER, true);//it's not really property, but have same syntax rules if ("param".equalsIgnoreCase(actionName)) { // See link above. eatSemicolon(myBuilder); } else { parseFunctionBody(myBuilder); } actionMarker.done(CfmlElementTypes.ACTION); } } private void parseStatement(PsiBuilder myBuilder) { // PsiBuilder.Marker statement = myBuilder.mark(); if (myBuilder.getTokenType() == IDENTIFIER && "property".equalsIgnoreCase(myBuilder.getTokenText()) && parseProperty(myBuilder)) { } else { (new CfmlExpressionParser(myBuilder)).parseStatement(); } if(myBuilder.getTokenType() == L_CURLYBRACKET) { parseScript(myBuilder, false); } else { eatSemicolon(myBuilder); } // statement.done(CfscriptElementTypes.STATEMENT); } private static void parseCondition(PsiBuilder myBuilder) { (new CfmlExpressionParser(myBuilder)).parseExpression(); } private static void parseInclude(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != INCLUDE_KEYWORD) { return; } PsiBuilder.Marker marker = myBuilder.mark(); myBuilder.advanceLexer(); IElementType tokenType = myBuilder.getTokenType(); if (tokenType != CfmlTokenTypes.SINGLE_QUOTE && tokenType != CfmlTokenTypes.DOUBLE_QUOTE) { marker.drop(); return; } (new CfmlExpressionParser(myBuilder)).parseString(); marker.done(CfmlElementTypes.INCLUDEEXPRESSION); } private static void parseImport(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != IMPORT_KEYWORD) { return; } PsiBuilder.Marker marker = myBuilder.mark(); myBuilder.advanceLexer(); IElementType tokenType = myBuilder.getTokenType(); if (tokenType == CfmlTokenTypes.SINGLE_QUOTE || tokenType == CfmlTokenTypes.DOUBLE_QUOTE) { (new CfmlExpressionParser(myBuilder)).parseString(); } else if (tokenType == IDENTIFIER) { (new CfmlExpressionParser(myBuilder)).parseComponentReference(); } marker.done(CfmlElementTypes.IMPORTEXPRESSION); } // eating numeric or string private static boolean parseConstant(PsiBuilder myBuilder) { IElementType tokenType = myBuilder.getTokenType(); if (tokenType == INTEGER || tokenType == DOUBLE || tokenType == BOOLEAN) { myBuilder.advanceLexer(); return true; } else if (tokenType == CfmlTokenTypes.SINGLE_QUOTE || tokenType == CfmlTokenTypes.DOUBLE_QUOTE) { myBuilder.advanceLexer(); tokenType = myBuilder.getTokenType(); if (tokenType != CfmlTokenTypes.SINGLE_QUOTE_CLOSER && tokenType != CfmlTokenTypes.DOUBLE_QUOTE_CLOSER && !myBuilder.eof()) { myBuilder.advanceLexer(); } tokenType = myBuilder.getTokenType(); if (tokenType != CfmlTokenTypes.SINGLE_QUOTE_CLOSER && tokenType != CfmlTokenTypes.DOUBLE_QUOTE_CLOSER) { myBuilder.error(CfmlBundle.message("cfml.parsing.quote.expected")); return true; } myBuilder.advanceLexer(); return true; } return false; } private boolean parseConditionInBrackets(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != L_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.bracket.expected")); return false; } myBuilder.advanceLexer(); parseCondition(myBuilder); if (myBuilder.getTokenType() != R_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.bracket.expected")); return true; } myBuilder.advanceLexer(); return true; } private void parseComponentOrInterface(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != COMPONENT_KEYWORD && myBuilder.getTokenType() != INTERFACE_KEYWORD) { return; } PsiBuilder.Marker componentMarker = myBuilder.mark(); boolean isComponent = myBuilder.getTokenType() == COMPONENT_KEYWORD; myBuilder.advanceLexer(); /* if (myBuilder.getTokenType() != IDENTIFIER) { // myBuilder.error("cfml.parsing.identifier.expected"); } else { final String nameOrAttribute = myBuilder.getTokenText(); final CfmlTagDescription componentTag = CfmlLangInfo.myTagAttributes.get("cfcomponent"); if (nameOrAttribute != null && !componentTag.hasAttribute(nameOrAttribute.toLowerCase())) { myBuilder.advanceLexer(); } } */ if (myBuilder.getTokenType() == FUNCTION_KEYWORD) { componentMarker.rollbackTo(); parseFunctionExpression(myBuilder, false); return; } CfmlParser.parseAttributes(myBuilder, isComponent ? "cfcomponent" : "cfinterface", IDENTIFIER, true); if (myBuilder.getTokenType() != L_CURLYBRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.open.curly.bracket.expected")); componentMarker.drop(); return; } myBuilder.advanceLexer(); if (myBuilder.getTokenType() == PAGEENCODING_KEYWORD) { myBuilder.advanceLexer(); IElementType tokenType = myBuilder.getTokenType(); if (tokenType == CfmlTokenTypes.SINGLE_QUOTE || tokenType == CfmlTokenTypes.DOUBLE_QUOTE) { (new CfmlExpressionParser(myBuilder)).parseString(); eatSemicolon(myBuilder); } else { myBuilder.error(CfmlBundle.message("cfml.parsing.string.expected")); } } parseScript(myBuilder, false, false, true); componentMarker.done(CfmlStubElementTypes.COMPONENT_DEFINITION); } private void parseIfExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != IF_KEYWORD) { return; } PsiBuilder.Marker ifExprMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (!parseConditionInBrackets(myBuilder)) { ifExprMarker.drop(); return; } parseScript(myBuilder, false); if (myBuilder.getTokenType() == ELSE_KEYWORD) { myBuilder.advanceLexer(); if (myBuilder.getTokenType() == IF_KEYWORD) { parseIfExpression(myBuilder); } else { parseScript(myBuilder, false); } } ifExprMarker.done(CfmlElementTypes.IFEXPRESSION); } private void parseWhileExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != WHILE_KEYWORD) { return; } PsiBuilder.Marker whileMarker = myBuilder.mark(); myBuilder.advanceLexer(); parseConditionInBrackets(myBuilder); parseScript(myBuilder, false); whileMarker.done(CfmlElementTypes.WHILEEXPRESSION); } private void parseDoWhileExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != DO_KEYWORD) { return; } PsiBuilder.Marker doWhileMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (myBuilder.getTokenType() != L_CURLYBRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.open.bracket.expected")); doWhileMarker.drop(); return; } parseScript(myBuilder, false); if (myBuilder.getTokenType() != WHILE_KEYWORD) { myBuilder.error(CfmlBundle.message("cfml.parsing.keyword.expected", "while")); doWhileMarker.done(CfmlElementTypes.DOWHILEEXPRESSION); return; } myBuilder.advanceLexer(); parseConditionInBrackets(myBuilder); if (myBuilder.getTokenType() != SEMICOLON) { myBuilder.error(CfmlBundle.message("cfml.parsing.semicolon.expected")); } else { myBuilder.advanceLexer(); } doWhileMarker.done(CfmlElementTypes.DOWHILEEXPRESSION); } private static void eatSemicolon(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != SEMICOLON) { myBuilder.error(CfmlBundle.message("cfml.parsing.semicolon.expected")); } else { myBuilder.advanceLexer(); } } private void parseForExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != FOR_KEYWORD) { return; } PsiBuilder.Marker forExpressionMarker = myBuilder.mark(); myBuilder.advanceLexer(); // eat opening bracket if (myBuilder.getTokenType() != L_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.bracket.expected")); forExpressionMarker.drop(); return; } myBuilder.advanceLexer(); if (!tryParseForIn(myBuilder)) { parseStatement(myBuilder); parseCondition(myBuilder); eatSemicolon(myBuilder); (new CfmlExpressionParser(myBuilder)).parseStatement(); } if (myBuilder.getTokenType() != R_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.bracket.expected")); forExpressionMarker.done(CfmlElementTypes.FOREXPRESSION); return; } myBuilder.advanceLexer(); parseScript(myBuilder, false); forExpressionMarker.done(CfmlElementTypes.FOREXPRESSION); } private static boolean tryParseForIn(PsiBuilder myBuilder) { PsiBuilder.Marker startMarker = myBuilder.mark(); if (myBuilder.getTokenType() == VAR_KEYWORD) { myBuilder.advanceLexer(); } PsiBuilder.Marker definitionMarker = myBuilder.mark(); if (!(new CfmlExpressionParser(myBuilder)).parseReference(false)) { startMarker.rollbackTo(); return false; } else { definitionMarker.done(CfmlElementTypes.FORVARIABLE); } if (myBuilder.getTokenType() != IN_L) { startMarker.rollbackTo(); return false; } myBuilder.advanceLexer(); if (!(new CfmlExpressionParser(myBuilder)).parseReference(false)) { (new CfmlExpressionParser(myBuilder)).parseArrayDefinition(); } startMarker.drop(); return true; } private void parseFunctionBody(PsiBuilder myBuilder) { PsiBuilder.Marker functionBodyMarker = myBuilder.mark(); if (myBuilder.getTokenType() != L_CURLYBRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.open.curly.bracket.expected")); functionBodyMarker.drop(); return; } parseScript(myBuilder, false); // TODO eat return keyword functionBodyMarker.done(CfmlElementTypes.FUNCTIONBODY); } /** * ColdFusion9: [required] [type] name [= default value (constant)], ... */ private void parseParametersList(PsiBuilder myBuilder) { PsiBuilder.Marker argumentMarker = myBuilder.mark(); // parsing required keyword is present if (myBuilder.getTokenType() == REQUIRED_KEYWORD) { myBuilder.advanceLexer(); } // try to parse type final PsiBuilder.Marker marker = myBuilder.mark(); if (!parseType(myBuilder) || myBuilder.getTokenType() != IDENTIFIER) { marker.rollbackTo(); } else { marker.drop(); } // parse parameter name if (myBuilder.getTokenType() == IDENTIFIER) { myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { // parse default value // TODO: to find out whether it can be something different from a constant myBuilder.advanceLexer(); final PsiBuilder.Marker defaultValueMarker = myBuilder.mark(); if (!parseConstant(myBuilder)) { parseRValue(myBuilder); } defaultValueMarker.done(CfmlElementTypes.VALUE); } if (myBuilder.getTokenType() == IDENTIFIER) { CfmlParser.parseAttributes(myBuilder, "cfparameter", IDENTIFIER, true); } argumentMarker.done(CfmlElementTypes.FUNCTION_ARGUMENT); if (myBuilder.getTokenType() == COMMA) { myBuilder.advanceLexer(); parseParametersList(myBuilder); } } else { argumentMarker.drop(); } } private void parseParametersListInBrackets(PsiBuilder myBuilder) { PsiBuilder.Marker argumentsList = myBuilder.mark(); eatLeftBracket(myBuilder); parseParametersList(myBuilder); eatRightBracket(myBuilder); argumentsList.done(CfmlElementTypes.PARAMETERS_LIST); } void parseFunctionExpression(PsiBuilder myBuilder, boolean anonymous) { PsiBuilder.Marker functionMarker = myBuilder.mark(); if (!anonymous) { if (ACCESS_KEYWORDS.contains(myBuilder.getTokenType())) { myBuilder.advanceLexer(); } if (myBuilder.getTokenType() != FUNCTION_KEYWORD) { parseType(myBuilder); } } if (myBuilder.getTokenType() != FUNCTION_KEYWORD) { myBuilder.error(CfmlBundle.message("cfml.parsing.function.expected")); functionMarker.drop(); return; } myBuilder.advanceLexer(); if (myBuilder.getTokenType() != IDENTIFIER && !(myBuilder.getTokenType() == DEFAULT_KEYWORD) && !anonymous) { myBuilder.error(CfmlBundle.message("cfml.parsing.identifier.expected")); } else { if (!anonymous) myBuilder.advanceLexer(); } parseParametersListInBrackets(myBuilder); CfmlParser.parseAttributes(myBuilder, "cffunction", IDENTIFIER, true); parseFunctionBody(myBuilder); functionMarker.done(CfmlElementTypes.FUNCTION_DEFINITION); } private void parseDOTDOTAndScript(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != DOTDOT) { myBuilder.error(CfmlBundle.message("cfml.parsing.dot.dot.expected")); } else { myBuilder.advanceLexer(); } if (myBuilder.getTokenType() != L_CURLYBRACKET) { if (myBuilder.getTokenType() == CASE_KEYWORD) { return; } int offset = myBuilder.getCurrentOffset(); while (!myBuilder.eof() && myBuilder.getTokenType() != BREAK_KEYWORD && myBuilder.getTokenType() != DEFAULT_KEYWORD && myBuilder.getTokenType() != CASE_KEYWORD && myBuilder.getTokenType() != R_CURLYBRACKET && !isEndOfScript(myBuilder)) { if (!parseScript(myBuilder, false)) { break; } if (offset == myBuilder.getCurrentOffset()) { break; } offset = myBuilder.getCurrentOffset(); } if (myBuilder.getTokenType() == BREAK_KEYWORD) { myBuilder.advanceLexer(); eatSemicolon(myBuilder); } } else { parseScript(myBuilder, false); } } private void parseCaseExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != CASE_KEYWORD) { return; } PsiBuilder.Marker caseExpressionMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (!parseConstant(myBuilder)) { if (myBuilder.getTokenType() == IDENTIFIER) { myBuilder.error(CfmlBundle.message("cfml.parsing.constant.expected")); myBuilder.advanceLexer(); } else { myBuilder.error(CfmlBundle.message("cfml.parsing.constant.expected")); } } parseDOTDOTAndScript(myBuilder); caseExpressionMarker.done(CfmlElementTypes.CASEEXPRESSION); } private void parseSwitchExpression(PsiBuilder myBuilder) { PsiBuilder.Marker switchMarker = myBuilder.mark(); if (myBuilder.getTokenType() != SWITCH_KEYWORD) { return; } myBuilder.advanceLexer(); if (!this.eatLeftBracket(myBuilder)) { switchMarker.drop(); return; } this.parseExpression(myBuilder); this.eatRightBracket(myBuilder); if (myBuilder.getTokenType() != L_CURLYBRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.open.curly.bracket.expected")); switchMarker.drop(); return; } myBuilder.advanceLexer(); while (myBuilder.getTokenType() == CASE_KEYWORD) { parseCaseExpression(myBuilder); } if (myBuilder.getTokenType() == DEFAULT_KEYWORD) { PsiBuilder.Marker caseExpressionMarker = myBuilder.mark(); myBuilder.advanceLexer(); parseDOTDOTAndScript(myBuilder); caseExpressionMarker.done(CfmlElementTypes.CASEEXPRESSION); } while (myBuilder.getTokenType() == CASE_KEYWORD) { parseCaseExpression(myBuilder); } if (myBuilder.getTokenType() != R_CURLYBRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.curly.bracket.expected")); } else { myBuilder.advanceLexer(); } switchMarker.done(CfmlElementTypes.SWITCHEXPRESSION); } private static boolean eatLeftBracket(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != L_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.open.bracket.expected")); return false; } myBuilder.advanceLexer(); return true; } private static void eatRightBracket(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != R_BRACKET) { myBuilder.error(CfmlBundle.message("cfml.parsing.close.bracket.expected")); return; } myBuilder.advanceLexer(); } private static boolean parseType(PsiBuilder myBuilder) { if (TYPE_KEYWORDS.contains(myBuilder.getTokenType())) { final PsiBuilder.Marker typeMarker = myBuilder.mark(); myBuilder.advanceLexer(); typeMarker.done(CfmlElementTypes.TYPE); } else { if (myBuilder.getTokenType() != IDENTIFIER) { myBuilder.error(CfmlBundle.message("cfml.parsing.type.expected")); return false; } final PsiBuilder.Marker typeMarker = myBuilder.mark(); myBuilder.advanceLexer(); while (myBuilder.getTokenType() == POINT) { myBuilder.advanceLexer(); if (myBuilder.getTokenType() != IDENTIFIER) { myBuilder.error(CfmlBundle.message("cfml.parsing.type.expected")); typeMarker.done(CfmlElementTypes.TYPE); return true; } myBuilder.advanceLexer(); } typeMarker.done(CfmlElementTypes.TYPE); } return true; } private void parseCatchExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != CATCH_KEYWORD) { return; } PsiBuilder.Marker catchExpressionMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (!eatLeftBracket(myBuilder)) { catchExpressionMarker.drop(); return; } parseType(myBuilder); if (myBuilder.getTokenType() != IDENTIFIER) { myBuilder.error(CfmlBundle.message("cfml.parsing.identifier.expected")); catchExpressionMarker.drop(); return; } myBuilder.advanceLexer(); eatRightBracket(myBuilder); catchExpressionMarker.done(CfmlElementTypes.CATCHEXPRESSION); parseScript(myBuilder, false); } private void parseTryCatchExpression(PsiBuilder myBuilder) { if (myBuilder.getTokenType() != TRY_KEYWORD) { return; } PsiBuilder.Marker tryCatchMarker = myBuilder.mark(); myBuilder.advanceLexer(); parseScript(myBuilder, false); while (myBuilder.getTokenType() == CATCH_KEYWORD) { parseCatchExpression(myBuilder); } if (myBuilder.getTokenType() == FINALLY_KEYWORD) { myBuilder.advanceLexer(); parseScript(myBuilder, false); } tryCatchMarker.done(CfmlElementTypes.TRYCATCHEXPRESSION); } public boolean parseScript(PsiBuilder myBuilder, boolean betweenScriptTags) { return parseScript(myBuilder, betweenScriptTags, true, false); } public boolean parseScript(PsiBuilder myBuilder, boolean betweenScriptTags, boolean createBlockOfStatments, boolean waitForRightBracket) { PsiBuilder.Marker blockOfStatements = null; if (myBuilder.getTokenType() == L_CURLYBRACKET) { waitForRightBracket = true; blockOfStatements = myBuilder.mark(); myBuilder.advanceLexer(); } while (!isEndOfScript(myBuilder)) { int lexerPosition = myBuilder.getCurrentOffset(); if (myBuilder.getTokenType() == INCLUDE_KEYWORD) { parseInclude(myBuilder); } else if (myBuilder.getTokenType() == IMPORT_KEYWORD) { parseImport(myBuilder); } else if (myBuilder.getTokenType() == COMPONENT_KEYWORD || myBuilder.getTokenType() == INTERFACE_KEYWORD) { parseComponentOrInterface(myBuilder); } else if (ACCESS_KEYWORDS.contains(myBuilder.getTokenType()) || myBuilder.getTokenType() == FUNCTION_KEYWORD ) { parseFunctionExpression(myBuilder, false); } else if (TYPE_KEYWORDS.contains(myBuilder.getTokenType())) { if (!tryParseStatement(myBuilder)) { parseFunctionExpression(myBuilder, false); } } else if (myBuilder.getTokenType() == VAR_KEYWORD) { parseStatement(myBuilder); } else if (myBuilder.getTokenType() == IF_KEYWORD) { parseIfExpression(myBuilder); } else if (myBuilder.getTokenType() == WHILE_KEYWORD) { parseWhileExpression(myBuilder); } else if (myBuilder.getTokenType() == DO_KEYWORD) { parseDoWhileExpression(myBuilder); } else if (myBuilder.getTokenType() == FOR_KEYWORD) { parseForExpression(myBuilder); } else if (myBuilder.getTokenType() == SWITCH_KEYWORD) { parseSwitchExpression(myBuilder); } else if (myBuilder.getTokenType() == RETHROW_KEYWORD) { myBuilder.advanceLexer(); eatSemicolon(myBuilder); } else if (myBuilder.getTokenType() == RETURN_KEYWORD) { parseReturnStatement(myBuilder); } else if (myBuilder.getTokenType() == BREAK_KEYWORD || myBuilder.getTokenType() == ABORT_KEYWORD) { myBuilder.advanceLexer(); eatSemicolon(myBuilder); } else if (CfmlUtil.isActionName(myBuilder)) { parseAction(myBuilder); } else if (myBuilder.getTokenType() == L_CURLYBRACKET) { parseScript(myBuilder, false); } else if (myBuilder.getTokenType() == R_CURLYBRACKET) { if (waitForRightBracket) { myBuilder.advanceLexer(); if (blockOfStatements != null) { if (createBlockOfStatments) { blockOfStatements.done(CfmlElementTypes.BLOCK_OF_STATEMENTS); } else { blockOfStatements.drop(); } } return true; } else { myBuilder.error(CfmlBundle.message("cfml.parsing.unexpected.token")); myBuilder.advanceLexer(); return false; } } else if (myBuilder.getTokenType() == TRY_KEYWORD) { parseTryCatchExpression(myBuilder); } else if (KEYWORDS.contains(myBuilder.getTokenType())) { if (myBuilder.getTokenType() == VAR_KEYWORD || myBuilder.getTokenType() == SCOPE_KEYWORD) { parseStatement(myBuilder); } else if (myBuilder.getTokenType() != CONTINUE_KEYWORD && myBuilder.getTokenType() != RETURN_KEYWORD && myBuilder.getTokenType() != BREAK_KEYWORD) { PsiBuilder.Marker errorMarker = myBuilder.mark(); myBuilder.advanceLexer(); errorMarker.error(CfmlBundle.message("cfml.parsing.unexpected.token")); } else { myBuilder.advanceLexer(); eatSemicolon(myBuilder); } } else { PsiBuilder.Marker marker = myBuilder.mark(); if (parseType(myBuilder) && myBuilder.getTokenType() == FUNCTION_KEYWORD) { marker.rollbackTo(); parseFunctionExpression(myBuilder, false); } else { marker.rollbackTo(); if (myBuilder.getTokenType() == IDENTIFIER) { PsiBuilder.Marker assignMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { assignMarker.rollbackTo(); new CfmlExpressionParser(myBuilder).parseExpression(); eatSemicolon(myBuilder); } else { assignMarker.rollbackTo(); parseStatement(myBuilder); } } else { parseStatement(myBuilder); } } } if (!betweenScriptTags && !waitForRightBracket) { break; } if (lexerPosition == myBuilder.getCurrentOffset()) { myBuilder.error(CfmlBundle.message("cfml.parsing.unexpected.token")); myBuilder.advanceLexer(); if (blockOfStatements != null) { blockOfStatements.drop(); } return false; } /* IN_KEYWORD, VAR_KEYWORD, */ } if (blockOfStatements != null) { blockOfStatements.drop(); } return true; } private boolean tryParseStatement(PsiBuilder myBuilder) { PsiBuilder.Marker referenceMarker = myBuilder.mark(); myBuilder.advanceLexer(); if (myBuilder.getTokenType() == CfmlTokenTypes.ASSIGN) { referenceMarker.rollbackTo(); parseStatement(myBuilder); return true; } referenceMarker.rollbackTo(); return false; } private static void parseReturnStatement(PsiBuilder myBuilder) { myBuilder.advanceLexer(); if (!(new CfmlExpressionParser(myBuilder)).parseStructureDefinition()) { if (!(new CfmlExpressionParser(myBuilder)).parseArrayDefinition()) { (new CfmlExpressionParser(myBuilder)).parseExpression(); } } eatSemicolon(myBuilder); } private static boolean isEndOfScript(PsiBuilder myBuilder) { return myBuilder.getTokenType() == null || myBuilder.getTokenType() == CfmlTokenTypes.OPENER || myBuilder.getTokenType() == CfmlTokenTypes.LSLASH_ANGLEBRACKET; } }