1 /*
2  * Permission is hereby granted, free of charge, to any person obtaining a copy of
3  * this software and associated documentation files (the "Software"), to deal in
4  * the Software without restriction, including without limitation the rights to
5  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
6  * of the Software, and to permit persons to whom the Software is furnished to do
7  * so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in all
10  * copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  */
20 package jdk.nashorn.internal.runtime.regexp.joni;
21 
22 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
23 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
24 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
25 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
26 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
27 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
28 import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
29 import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
30 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
31 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
32 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
33 import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;
34 
35 abstract class Compiler implements ErrorMessages {
36     protected final Analyser analyser;
37     protected final Regex regex;
38 
Compiler(final Analyser analyser)39     protected Compiler(final Analyser analyser) {
40         this.analyser = analyser;
41         this.regex = analyser.regex;
42     }
43 
compile()44     final void compile() {
45         prepare();
46         compileTree(analyser.root);
47         finish();
48     }
49 
prepare()50     protected abstract void prepare();
finish()51     protected abstract void finish();
52 
compileAltNode(ConsAltNode node)53     protected abstract void compileAltNode(ConsAltNode node);
54 
compileStringRawNode(final StringNode sn)55     private void compileStringRawNode(final StringNode sn) {
56         if (sn.length() <= 0) {
57             return;
58         }
59         addCompileString(sn.chars, sn.p, sn.length(), false);
60     }
61 
compileStringNode(final StringNode node)62     private void compileStringNode(final StringNode node) {
63         final StringNode sn = node;
64         if (sn.length() <= 0) {
65             return;
66         }
67 
68         final boolean ambig = sn.isAmbig();
69 
70         int p, prev;
71         p = prev = sn.p;
72         final int end = sn.end;
73         final char[] chars = sn.chars;
74         p++;
75         int slen = 1;
76 
77         while (p < end) {
78             slen++;
79             p++;
80         }
81         addCompileString(chars, prev, slen, ambig);
82     }
83 
addCompileString(char[] chars, int p, int strLength, boolean ignoreCase)84     protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
85 
compileCClassNode(CClassNode node)86     protected abstract void compileCClassNode(CClassNode node);
compileAnyCharNode()87     protected abstract void compileAnyCharNode();
compileBackrefNode(BackRefNode node)88     protected abstract void compileBackrefNode(BackRefNode node);
compileNonCECQuantifierNode(QuantifierNode node)89     protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
compileOptionNode(EncloseNode node)90     protected abstract void compileOptionNode(EncloseNode node);
compileEncloseNode(EncloseNode node)91     protected abstract void compileEncloseNode(EncloseNode node);
compileAnchorNode(AnchorNode node)92     protected abstract void compileAnchorNode(AnchorNode node);
93 
compileTree(final Node node)94     protected final void compileTree(final Node node) {
95         switch (node.getType()) {
96         case NodeType.LIST:
97             ConsAltNode lin = (ConsAltNode)node;
98             do {
99                 compileTree(lin.car);
100             } while ((lin = lin.cdr) != null);
101             break;
102 
103         case NodeType.ALT:
104             compileAltNode((ConsAltNode)node);
105             break;
106 
107         case NodeType.STR:
108             final StringNode sn = (StringNode)node;
109             if (sn.isRaw()) {
110                 compileStringRawNode(sn);
111             } else {
112                 compileStringNode(sn);
113             }
114             break;
115 
116         case NodeType.CCLASS:
117             compileCClassNode((CClassNode)node);
118             break;
119 
120         case NodeType.CANY:
121             compileAnyCharNode();
122             break;
123 
124         case NodeType.BREF:
125             compileBackrefNode((BackRefNode)node);
126             break;
127 
128         case NodeType.QTFR:
129             compileNonCECQuantifierNode((QuantifierNode)node);
130             break;
131 
132         case NodeType.ENCLOSE:
133             final EncloseNode enode = (EncloseNode)node;
134             if (enode.isOption()) {
135                 compileOptionNode(enode);
136             } else {
137                 compileEncloseNode(enode);
138             }
139             break;
140 
141         case NodeType.ANCHOR:
142             compileAnchorNode((AnchorNode)node);
143             break;
144 
145         default:
146             // undefined node type
147             newInternalException(ERR_PARSER_BUG);
148         } // switch
149     }
150 
compileTreeNTimes(final Node node, final int n)151     protected final void compileTreeNTimes(final Node node, final int n) {
152         for (int i=0; i<n; i++) {
153             compileTree(node);
154         }
155     }
156 
newSyntaxException(final String message)157     protected void newSyntaxException(final String message) {
158         throw new SyntaxException(message);
159     }
160 
newInternalException(final String message)161     protected void newInternalException(final String message) {
162         throw new InternalException(message);
163     }
164 }
165