PsyMatcher.java
package coneforest.psylla.core;
import coneforest.psylla.runtime.*;
import java.util.regex.Matcher;
/**
* The representation of {@code matcher}.
*/
@Type("matcher")
public class PsyMatcher
implements PsyResetable
{
/**
* Context action of the {@code capturegroup} operator.
*/
@OperatorType("capturegroup")
public static final ContextAction PSY_CAPTUREGROUP=oContext->
{
final var ostack=oContext.operandStackBacked(2);
try
{
final var matcher=((PsyMatcher)ostack.getBacked(0)).matcher;
final var oKey=ostack.getBacked(1);
if(oKey instanceof PsyInteger oIntegerKey)
{
final var index=oIntegerKey.intValue();
final var group=matcher.group(index);
if(group!=null)
{
ostack.push(new PsyString(group));
ostack.push(PsyInteger.of(matcher.start(index)));
ostack.push(PsyInteger.of(matcher.end(index)));
}
ostack.push(PsyBoolean.of(group!=null));
}
else if(oKey instanceof PsyTextual oTextualKey)
{
final var key=oTextualKey.stringValue();
final var group=matcher.group(key);
if(group!=null)
{
ostack.push(new PsyString(group));
ostack.push(PsyInteger.of(matcher.start(key)));
ostack.push(PsyInteger.of(matcher.end(key)));
}
ostack.push(PsyBoolean.of(group!=null));
}
else
throw new PsyTypeCheckException();
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException();
}
catch(final IllegalArgumentException ex)
{
throw new PsyUndefinedException();
}
catch(final IllegalStateException ex)
{
throw new PsyInvalidStateException();
}
};
/**
* Context action of the {@code capturegroupcount} operator.
*/
@OperatorType("capturegroupcount")
public static final ContextAction PSY_CAPTUREGROUPCOUNT
=ContextAction.<PsyMatcher>ofFunction(PsyMatcher::psyCaptureGroupCount);
/**
* Context action of the {@code find} operator.
*/
@OperatorType("find")
public static final ContextAction PSY_FIND
=ContextAction.<PsyMatcher>ofFunction(PsyMatcher::psyFind);
/**
* Context action of the {@code matcher} operator.
*/
@OperatorType("matcher")
public static final ContextAction PSY_MATCHER
=ContextAction.<PsyTextual, PsyRegExp>ofBiFunction(PsyMatcher::new);
/**
* Context action of the {@code matches} operator.
*/
@OperatorType("matches")
public static final ContextAction PSY_MATCHES
=ContextAction.<PsyMatcher>ofFunction(PsyMatcher::psyMatches);
/**
* Context action of the {@code replaceall} operator.
*/
@OperatorType("replaceall")
public static final ContextAction PSY_REPLACEALL
=ContextAction.<PsyMatcher, PsyTextual>ofBiFunction(PsyMatcher::psyReplaceAll);
private final Matcher matcher;
public PsyMatcher(final PsyTextual oTextual, final PsyRegExp oRegExp)
{
matcher=oRegExp.getPattern().matcher(oTextual.stringValue());
}
@Override
public void psyReset()
{
matcher.reset();
}
public PsyBoolean psyMatches()
{
return PsyBoolean.of(matcher.matches());
}
public PsyBoolean psyFind()
{
return PsyBoolean.of(matcher.find());
}
public PsyString psyReplaceAll(final PsyTextual oReplacement)
{
return new PsyString(matcher.replaceAll(oReplacement.stringValue()));
}
public PsyInteger psyCaptureGroupCount()
{
return PsyInteger.of(matcher.groupCount());
}
public PsyInteger psyCaptureGroupStart(final PsyObject oKey)
throws PsyInvalidStateException, PsyRangeCheckException, PsyTypeCheckException, PsyUndefinedException
{
try
{
final int start;
if(oKey instanceof PsyInteger oIntegerKey)
start=matcher.start(oIntegerKey.intValue());
else if(oKey instanceof PsyTextual oTextualKey)
start=matcher.start(oTextualKey.stringValue());
else
throw new PsyTypeCheckException();
return start>=0? PsyInteger.of(start): null;
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException();
}
catch(final IllegalArgumentException ex)
{
throw new PsyUndefinedException();
}
catch(final IllegalStateException ex)
{
throw new PsyInvalidStateException();
}
}
public PsyInteger psyCaptureGroupEnd(final PsyObject oKey)
throws PsyInvalidStateException, PsyRangeCheckException, PsyTypeCheckException, PsyUndefinedException
{
try
{
final int end;
if(oKey instanceof PsyInteger oIntegerKey)
end=matcher.start(oIntegerKey.intValue());
else if(oKey instanceof PsyTextual oTextualKey)
end=matcher.start(oTextualKey.stringValue());
else
throw new PsyTypeCheckException();
return end>=0? PsyInteger.of(end): null;
}
catch(final IndexOutOfBoundsException ex)
{
throw new PsyRangeCheckException();
}
catch(final IllegalArgumentException ex)
{
throw new PsyUndefinedException();
}
catch(final IllegalStateException ex)
{
throw new PsyInvalidStateException();
}
}
}