FunctionParsing.java

1    /* 
2     * Copyright 2000-2005 JetBrains s.r.o. 
3     * 
4     * Licensed under the Apache License, Version 2.0 (the "License"); 
5     * you may not use this file except in compliance with the License. 
6     * You may obtain a copy of the License at 
7     * 
8     * http://www.apache.org/licenses/LICENSE-2.0 
9     * 
10    * Unless required by applicable law or agreed to in writing, software 
11    * distributed under the License is distributed on an "AS IS" BASIS, 
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13    * See the License for the specific language governing permissions and 
14    * limitations under the License. 
15    */ 
16   package com.intellij.lang.javascript.parsing; 
17    
18   import com.intellij.lang.PsiBuilder; 
19   import com.intellij.lang.javascript.JSElementTypes; 
20   import com.intellij.lang.javascript.JSTokenTypes; 
21   import com.intellij.openapi.diagnostic.Logger; 
22    
23   /** 
24    * Created by IntelliJ IDEA. 
25    * User: max 
26    * Date: Jan 28, 2005 
27    * Time: 1:20:19 PM 
28    * To change this template use File | Settings | File Templates. 
29    */ 
30   public class FunctionParsing { 
31     private static final Logger LOG = Logger.getInstance("#com.intellij.lang.javascript.parsing.FunctionParsing"); 
32    
33     private FunctionParsing() { }   
34    
35     public static void parseFunctionExpression(PsiBuilder builder) { 
36       parseFunction(builder, true); 
37     } 
38    
39     public static void parseFunctionDeclaration(PsiBuilder builder) { 
40       parseFunction(builder, false); 
41     } 
42    
43     private static void parseFunction(PsiBuilder builder, boolean expressionContext) { 
44       final PsiBuilder.Marker functionMarker = builder.mark(); 
45       if (builder.getTokenType() == JSTokenTypes.FUNCTION_KEYWORD) { // function keyword may be ommited in context of get/set property definition 
46         builder.advanceLexer(); 
47       } 
48    
49       // Function name 
50       if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { 
51         builder.advanceLexer(); 
52       } 
53       else { 
54         if (!expressionContext) { 
55           builder.error("function name expected"); 
56         } 
57       } 
58    
59       parseParameterList(builder); 
60    
61       StatementParsing.parseFunctionBody(builder); 
62    
63       functionMarker.done(expressionContext ? JSElementTypes.FUNCTION_EXPRESSION : JSElementTypes.FUNCTION_DECLARATION); 
64     } 
65    
66     private static void parseParameterList(final PsiBuilder builder) { 
67       final PsiBuilder.Marker parameterList; 
68       if (builder.getTokenType() != JSTokenTypes.LPAR) { 
69         builder.error("( expected"); 
70         parameterList = builder.mark(); // To have non-empty parameters list at all the time. 
71         parameterList.done(JSElementTypes.PARAMETER_LIST); 
72         return; 
73       } 
74       else { 
75         parameterList = builder.mark(); 
76         builder.advanceLexer(); 
77       } 
78    
79       boolean first = true; 
80       while (builder.getTokenType() != JSTokenTypes.RPAR) { 
81         if (first) { 
82           first = false; 
83         } 
84         else { 
85           if (builder.getTokenType() == JSTokenTypes.COMMA) { 
86             builder.advanceLexer(); 
87           } 
88           else { 
89             builder.error(", or ) expected"); 
90             break; 
91           } 
92         } 
93    
94         final PsiBuilder.Marker parameter = builder.mark(); 
95         if (builder.getTokenType() == JSTokenTypes.IDENTIFIER) { 
96           builder.advanceLexer(); 
97           parameter.done(JSElementTypes.FORMAL_PARAMETER); 
98         } 
99         else { 
100          builder.error("formal parameter name expected"); 
101          parameter.rollbackTo(); 
102        } 
103      } 
104   
105      if (builder.getTokenType() == JSTokenTypes.RPAR) { 
106        builder.advanceLexer(); 
107      } 
108   
109      parameterList.done(JSElementTypes.PARAMETER_LIST); 
110    } 
111  } 
112