001 
002 /*
003  *  JScripter Simulation 1.0 - For Java To Script
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.sim;
021 
022 import java.util.regex.Matcher;
023 import java.util.regex.Pattern;
024 
025 import org.jscripter.sim.core.Core;
026 
027 
028 import js.ArrayLike;
029 import js.Js;
030 import js.RegExpLike;
031 import js.core.JsGlobal;
032 import js.core.JsRegExp;
033 
034 class SimRegExpLike implements RegExpLike
035 {
036     private final String regex;
037     private final String flags;
038     private final boolean global;
039     private final boolean ignoreCase;
040     private final boolean multiline;
041     private Integer lastIndex = 0;
042     private Pattern pattern = null;
043 
044     public SimRegExpLike(String regex, String flags) {
045         this.regex = regex;
046         this.flags = flags;
047         boolean g = false, i = false, m = false;
048         for (char c : flags.toCharArray()) {
049             switch (c)
050             {
051                 case 'g':
052                 case 'G':
053                     g = true;
054                     break;
055                 case 'i':
056                 case 'I':
057                     i = true;
058                     break;
059                 case 'm':
060                 case 'M':
061                     m = true;
062                     break;
063                 default:
064             }
065         }
066         global = g;
067         ignoreCase = i;
068         multiline = m;
069     }
070     public SimRegExpLike(String regex) {
071         this.regex = regex;
072         this.flags = null;
073         global     = false;
074         ignoreCase = false;
075         multiline  = false;
076     }
077 
078     public final Pattern pattern() {
079         if (pattern == null) {
080             int flags = 0;
081             if (ignoreCase) {
082                 flags = Pattern.CASE_INSENSITIVE;
083             }
084             if (multiline) {
085                 flags |= Pattern.MULTILINE;
086             }
087             pattern = Pattern.compile(regex, flags);
088         }
089         return pattern;
090     }
091     //@Override
092     public final synchronized ArrayLike<?> exec(Object s) {
093         Matcher m = pattern().matcher(Js.toString(s));
094         boolean ret = false;
095         if (global()) {
096             ret = m.find(lastIndex);
097             lastIndex = ret ? m.end() : 0;
098         } else {
099             ret = m.find();
100         }
101         if (ret) {
102             SimArrayMatched a = new SimArrayMatched();
103             a.index(m.start());
104             a.input(Js.toString(s));
105             for (int i = 0, n = m.groupCount(); i < n; i++) {
106                 a.push(m.group(i));
107             }
108             return a;
109         } else {
110             return null;
111         }
112     }
113     //@Override
114     public final boolean global() {
115         return global;
116     }
117     //@Override
118     public final boolean ignoreCase() {
119         return ignoreCase;
120     }
121     //@Override
122     public final Integer lastIndex() {
123         return lastIndex;
124     }
125     //@Override
126     public final synchronized Integer lastIndex(Integer lastIndex) {
127         return this.lastIndex = lastIndex;
128     }
129     //@Override
130     public final boolean multiline() {
131         return multiline;
132     }
133     //@Override
134     public final String source() {
135         return regex;
136     }
137     //@Override
138     public final synchronized boolean test(Object s) {
139         Matcher m = pattern().matcher(Js.toString(s));
140         if (global()) {
141             boolean ret = m.find(lastIndex);
142             lastIndex = ret ? m.end() : 0;
143             return ret;
144         } else {
145             return m.find();
146         }
147     }
148     //@Override
149     public final String toString() {
150         StringBuilder sb = new StringBuilder();
151         sb.append("\\/");
152         sb.append(regex);
153         sb.append("\\/");
154         if (global) {
155             sb.append('g');
156         }
157         if (ignoreCase) {
158             sb.append('i');
159         }
160         if (multiline) {
161             sb.append('m');
162         }
163         return sb.toString();
164     }
165 
166     //@Override
167     public final RegExpLike valueOf() {
168         return this;
169     }
170 
171     //@Override
172     public final JsRegExp var() {
173         if (Core.isRunning()) {
174             return JsGlobal.RegExp.with().create(this);
175         } else {
176             if (flags == null) {
177                 return JsGlobal.RegExp.with().create(regex);
178             } else {
179                 return JsGlobal.RegExp.with().create(regex, flags);
180             }
181         }
182     }
183 }