view src/luan/modules/RegexLuan.java @ 1830:d72a52232f79

mail - minor
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 24 Sep 2024 17:17:57 -0600
parents e59349d53fec
children
line wrap: on
line source

package luan.modules;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import luan.Luan;
import luan.LuanMutable;
import luan.LuanTable;
import luan.LuanFunction;
import luan.LuanException;


public final class RegexLuan implements LuanMutable {
	public Pattern pattern;
	private boolean immutable = false;

	public RegexLuan(String s) {
		this.pattern = Pattern.compile(s);
	}

	@Override public boolean isImmutable() {
		return immutable;
	}

	@Override public void makeImmutable() {
		if(immutable)
			return;
		immutable = true;
	}

	public void set(String s) throws LuanException {
		if( immutable )
			throw new LuanException("regex is immutable");
		this.pattern = Pattern.compile(s);
	}

	public Object[] find(String s,Integer init) throws LuanException {
		int start = StringLuan.start(s,init,0);
		Matcher m = pattern.matcher(s);
		if( !m.find(start) )
			return null;
		int n = m.groupCount();
		Object[] rtn = new Object[2+n];
		rtn[0] = m.start() + 1;
		rtn[1] = m.end();
		for( int i=0; i<n; i++ ) {
			rtn[2+i] = m.group(i+1);
		}
		return rtn;
	}

	public LuanFunction gmatch(String s) throws LuanException {
		Utils.checkNotNull(s);
		final Matcher m = pattern.matcher(s);
		return new LuanFunction() {
			@Override public Object call(Luan luan,Object[] args) {
				if( !m.find() )
					return null;
				final int n = m.groupCount();
				if( n == 0 )
					return m.group();
				String[] rtn = new String[n];
				for( int i=0; i<n; i++ ) {
					rtn[i] = m.group(i+1);
				}
				return rtn;
			}
		};
	}

	public Object[] gsub(Luan luan,String s,Object repl,Integer n) throws LuanException {
		Utils.checkNotNull(s);
		int max = n==null ? Integer.MAX_VALUE : n;
		final Matcher m = pattern.matcher(s);
		if( max <= 0 || !m.find() )
			return new Object[]{ s, 0 };
		if( repl instanceof String ) {
			String replacement = (String)repl;
			int i = 0;
			StringBuffer sb = new StringBuffer();
			do {
				m.appendReplacement(sb,replacement);
				i++;
			} while( i<max && m.find() );
			m.appendTail(sb);
			return new Object[]{ sb.toString(), i };
		}
		if( repl instanceof LuanTable ) {
			LuanTable t = (LuanTable)repl;
			int i = 0;
			StringBuffer sb = new StringBuffer();
			do {
				String match = m.groupCount()==0 ? m.group() : m.group(1);
				Object val = t.get(luan,match);
				if( val != null ) {
					String replacement = luan.luanToString(val);
					m.appendReplacement(sb,replacement);
				}
				i++;
			} while( i<max && m.find() );
			m.appendTail(sb);
			return new Object[]{ sb.toString(), i };
		}
		if( repl instanceof LuanFunction ) {
			LuanFunction fn = (LuanFunction)repl;
			int i = 0;
			StringBuffer sb = new StringBuffer();
			do {
				Object[] args;
				final int count = m.groupCount();
				if( count == 0 ) {
					args = new String[]{m.group()};
				} else {
					args = new String[count];
					for( int j=0; j<count; j++ ) {
						args[j] = m.group(j+1);
					}
				}
				Object val = Luan.first( fn.call(luan,args) );
				if( val != null ) {
					String replacement = luan.luanToString(val);
					m.appendReplacement(sb,replacement);
				}
				i++;
			} while( i<max && m.find() );
			m.appendTail(sb);
			return new Object[]{ sb.toString(), i };
		}
		throw new LuanException( "bad argument #3 to 'gsub' (string/function/table expected)" );
	}

	public String[] match(String s,Integer init) throws LuanException {
		int start = StringLuan.start(s,init,0);
		Matcher m = pattern.matcher(s);
		if( !m.find(start) )
			return null;
		int n = m.groupCount();
		if( n == 0 )
			return new String[]{m.group()};
		String[] rtn = new String[n];
		for( int i=0; i<n; i++ ) {
			rtn[i] = m.group(i+1);
		}
		return rtn;
	}

	public boolean matches(String s) {
		return pattern.matcher(s).find();
	}

	public String[] split(String s,Integer limit) throws LuanException {
		Utils.checkNotNull(s);
		int n = limit==null ? -1 : limit;
		return pattern.split(s,n);
	}
}