org.drools.compiler.lang.dsl.AntlrDSLMappingEntry Maven / Gradle / Ivy
/*
* Copyright 2006 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.compiler.lang.dsl;
import java.util.Map;
import java.util.regex.Pattern;
import org.mvel2.util.ParseTools;
/**
* An ANTLR-driven implementation for the DSL Mapping Entry interface
*/
public class AntlrDSLMappingEntry extends AbstractDSLMappingEntry {
public AntlrDSLMappingEntry() {
this(ANY,
EMPTY_METADATA,
null,
null,
null,
null );
}
public AntlrDSLMappingEntry(final Section section,
final MetaData metadata,
final String key,
final String value,
final String keyPattern,
final String valuePattern) {
setSection( section );
setMetaData( metadata );
setMappingKey( key );
setMappingValue( value );
setKeyPattern( keyPattern );
setValuePattern( valuePattern );
}
/**
* @param KEY
* the key to set
*/
public void setKeyPattern(final String keyPat) {
//the "key" in this case is already mostly formed into
//a pattern by ANTLR, and just requires a bit of post-processing.
if ( keyPat != null ) {
String trimmed = keyPat.trim();
// escaping the special character $
String keyPattern = trimmed.replaceAll( "\\$", "\\\\\\$" );
// unescaping the special character #
keyPattern = keyPattern.replaceAll( "\\\\#", "#" );
if ( !keyPattern.startsWith( "^" ) ) {
// making it start after a non word char or at line start
// JDK 5 (java version 1.5.0_22) is buggy: doesn't handle alternatives within
// zero-width lookbehind assertions. As a workaround, we use an alternative of
// zero-width lookbehind assertions, slightly longer, but simpler than anything else.
// keyPattern = "(?<=\\W|^)" + keyPattern; // works in JDK >=6
keyPattern = "(?:(?<=^)|(?<=\\W))" + keyPattern;
}
// If the pattern ends with a pure variable whose pattern could create
// a greedy match, append a line end to avoid multiple line matching
if ( keyPattern.endsWith( "(.*?)" ) ) {
keyPattern += "$";
} else {
keyPattern += "(?=\\W|$)";
}
// fix variables offset
fixVariableOffsets();
// setting the key pattern and making it space insensitive
//first, look to see if it's
if ( trimmed.startsWith( "-" ) && (!trimmed.startsWith( "-\\s*" )) ) {
int index = keyPattern.indexOf( '-' ) + 1;
keyPattern = keyPattern.substring( 0, index ) + "\\s*" + keyPattern.substring( index ).trim();
}
// Make the pattern space insensitive.
keyPattern = keyPattern.replaceAll( "\\s+", "\\\\s+" );
// normalize duplications
keyPattern = keyPattern.replaceAll( "(\\\\s\\+)+", "\\\\s+" );
setKeyPattern( Pattern.compile( keyPattern, Pattern.DOTALL | Pattern.MULTILINE ) );
} else {
setKeyPattern( (Pattern) null );
}
}
private void fixVariableOffsets() {
char[] input = getMappingKey().toCharArray();
int counter = 1;
boolean insideCurly = false;
for ( int i = 0; i < input.length; i++ ) {
switch ( input[i] ) {
case '\\' :
// next char is escaped
i++;
break;
case '(' :
// Don't count /.{x(y}./ or /.(?./
if( ! insideCurly &&
(i == input.length - 1 || input[i+1] != '?' ) ) counter++;
break;
case '{' :
if ( insideCurly ) {
i = ParseTools.balancedCapture( input,
i,
'{' );
} else {
insideCurly = true;
updateVariableIndex( i,
counter );
counter++;
}
break;
case '}' :
if ( insideCurly ) insideCurly = false;
}
}
}
private void updateVariableIndex(int offset,
int counter) {
String subs = getMappingKey().substring( offset );
for ( Map.Entry entry : getVariables().entrySet() ) {
if ( subs.startsWith( "{" + entry.getKey() ) && ((subs.charAt( entry.getKey().length() + 1 ) == '}') || (subs.charAt( entry.getKey().length() + 1 ) == ':')) ) {
entry.setValue( Integer.valueOf( counter ) );
break;
}
}
}
/**
* @param value
* the value to set
*/
public void setValuePattern(String value) {
if ( value != null ) {
StringBuilder valuePatternBuffer = new StringBuilder();
valuePatternBuffer.append( value );
if ( value.endsWith( " " ) ) {
valuePatternBuffer.deleteCharAt( valuePatternBuffer.length() - 1 );
}
// unescaping the special character # and creating the line breaks
String pat = valuePatternBuffer.toString().replaceAll( "\\\\(#|\\{|\\})", "$1" ).
replaceAll( "\\\\n", "\n" ).
replaceAll( "\\\\\\$", "\\$" );
super.setValuePattern( pat );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy