View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl2.parser;
18  
19  import org.apache.commons.jexl2.DebugInfo;
20  import org.apache.commons.jexl2.JexlEngine;
21  import org.apache.commons.jexl2.JexlException;
22  
23  /**
24   * The base class for parsing, manages the parameter/local variable frame.
25   * @author henri
26   */
27  public class JexlParser extends StringParser {
28      /**
29       * The map of named registers aka script parameters.
30       * Each parameter is associated to a register and is materialized as an offset in the registers array used
31       * during evaluation.
32       */
33      protected JexlEngine.Scope frame;
34  
35      /**
36       * Sets the frame to use bythis parser.
37       * <p>
38       * This is used to allow parameters to be declared before parsing.
39       * </p>
40       * @param theFrame the register map
41       */
42      public void setFrame(JexlEngine.Scope theFrame) {
43          frame = theFrame;
44      }
45      
46      /**
47       * Gets the frame used by this parser.
48       * <p>
49       * Since local variables create new named registers, it is important to regain access after
50       * parsing to known which / how-many registers are needed.
51       * </p>
52       * @return the named register map
53       */
54      public JexlEngine.Scope getFrame() {
55          return frame;
56      }
57      
58  
59      /**
60       * Checks whether an identifier is a local variable or argument, ie stored in a register. 
61       * @param identifier the identifier
62       * @param image the identifier image
63       * @return the image
64       */
65      public String checkVariable(ASTIdentifier identifier, String image) {
66          if (frame != null) {
67              Integer register = frame.getRegister(image);
68              if (register != null) {
69                  identifier.setRegister(register.intValue());
70              }
71          }
72          return image;
73      }
74  
75      /**
76       * Declares a local variable.
77       * <p>
78       * This method creates an new entry in the named register map.
79       * </p>
80       * @param identifier the identifier used to declare
81       * @param image the variable name
82       */
83      public void declareVariable(ASTVar identifier, String image) {
84          if (frame == null) {
85              frame = new JexlEngine.Scope((String[])null);
86          }
87          Integer register = frame.declareVariable(image);
88          identifier.setRegister(register.intValue());
89          identifier.image = image;
90      }
91  
92      /**
93       * Default implementation does nothing but is overriden by generated code.
94       * @param top whether the identifier is beginning an l/r value
95       * @throws ParseException subclasses may throw this 
96       */
97      public void Identifier(boolean top) throws ParseException {
98          // Overriden by generated code
99      }
100 
101     final public void Identifier() throws ParseException {
102         Identifier(false);
103     }
104 
105     public Token getToken(int index) {
106         return null;
107     }
108 
109     void jjtreeOpenNodeScope(JexlNode n) {
110     }
111 
112     /**
113      * Ambiguous statement detector.
114      * @param n the node
115      * @throws ParseException 
116      */
117     void jjtreeCloseNodeScope(JexlNode n) throws ParseException {
118         if (n instanceof ASTAmbiguous && n.jjtGetNumChildren() > 0) {
119             DebugInfo dbgInfo = null;
120             Token tok = this.getToken(0);
121             if (tok != null) {
122                 dbgInfo = new DebugInfo(tok.image, tok.beginLine, tok.beginColumn);
123             } else {
124                 dbgInfo = n.debugInfo();
125             }
126             throw new JexlException.Parsing(dbgInfo, "Ambiguous statement, missing ';' between expressions", null);
127         }
128     }
129 }