/** * (c) 2011, Alejandro Serrano * Released under the terms of the EPL. */ package net.sf.eclipsefp.haskell.ui.internal.editors.partitioned; import java.util.ArrayList; import net.sf.eclipsefp.haskell.core.codeassist.ITokenTypes; import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.text.ScionTokenScanner; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.EndOfLineRule; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.ITokenScanner; import org.eclipse.jface.text.rules.PatternRule; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.rules.WordPatternRule; import org.eclipse.jface.text.source.ISourceViewer; /** * Configuration for highlighting of UUAGC files. * @author Alejandro Serrano * */ public class UuagcSourceViewerConfiguration extends PartitionSourceViewerConfiguration { private static String[] symbols = new String[] { "[", "|", "]", "=>", "=", "::", ":" }; private static String[] keywords = new String[] { "data", "attr", "sem", "deriving", "use", "type", "include", "ext", "merge", "as", "uniqueref", "around", "pragma", "module", "attach" }; private static String[] onlySmallKeywords = new String[] { "inh", "syn" }; private static String[] specialVariables = new String[] { "lhs", "loc" }; private static String[] types = new String[] { "Maybe", "Either", "Map", "IntMap", "self" }; public UuagcSourceViewerConfiguration( final PartitionEditor editor ) { super( editor ); } @Override public IPresentationReconciler getPresentationReconciler( final ISourceViewer viewer ) { PresentationReconciler reconciler = new PresentationReconciler(); reconciler.setDocumentPartitioning( PartitionDocumentSetup.PARTITIONING ); IFile file = ( editor != null ? editor.findFile() : null ); // ITokenScanner codeScanner = new PartitionedScionTokenScanner( // getScannerManager(), file, new String[] { "{" }, // new String[] { "}" }, new String[] { "{-" }, new String[] { "-}" } ); ScionTokenScanner codeScanner = new ScionTokenScanner( getScannerManager(), file ); DefaultDamagerRepairer haskellDr = new DefaultDamagerRepairer( codeScanner ); reconciler.setDamager( haskellDr, PartitionDocumentSetup.HASKELL ); reconciler.setRepairer( haskellDr, PartitionDocumentSetup.HASKELL ); DefaultDamagerRepairer uuagcDr = new DefaultDamagerRepairer( createUuagcScanner() ); reconciler.setDamager( uuagcDr, IDocument.DEFAULT_CONTENT_TYPE ); reconciler.setRepairer( uuagcDr, IDocument.DEFAULT_CONTENT_TYPE ); if (editor!=null){ editor.setTokenScanner( codeScanner ); } return reconciler; } private ITokenScanner createUuagcScanner() { RuleBasedScanner scanner = new RuleBasedScanner(); // Patterns WordPatternRule vars = new WordPatternRule( KeywordDetector.NO_DIGIT_AT_START_DETECTOR, "@", "", tokenByTypes.get( ITokenTypes.PREPROCESSOR_TEXT ) ); PatternRule string = new PatternRule( "\"", "\"", tokenByTypes.get( ITokenTypes.LITERAL_STRING ), '\\', true ); EndOfLineRule comment = new EndOfLineRule( "-- ", tokenByTypes.get( ITokenTypes.LITERATE_COMMENT ) ); ArrayList<IRule> rules = new ArrayList<>(); rules.add( vars ); rules.add( string ); rules.add( comment ); for( String symbol: symbols ) { rules.add( createRuleForToken( symbol, ITokenTypes.SYMBOL_RESERVED ) ); } for( String keyword: keywords ) { rules.add( createRuleForToken( keyword, ITokenTypes.KEYWORD ) ); rules.add( createRuleForToken( keyword.toUpperCase(), ITokenTypes.KEYWORD ) ); } for( String keyword: onlySmallKeywords ) { rules.add( createRuleForToken( keyword, ITokenTypes.KEYWORD ) ); } for( String var: specialVariables ) { rules.add( createRuleForToken( var, ITokenTypes.PREPROCESSOR_TEXT ) ); } for( String type: types ) { rules .add( createRuleForToken( type, ITokenTypes.IDENTIFIER_CONSTRUCTOR ) ); rules.add( createRuleForToken( type.toUpperCase(), ITokenTypes.IDENTIFIER_CONSTRUCTOR ) ); } IRule names = new IRule() { @Override public IToken evaluate( final ICharacterScanner scanner ) { // First we need an uppercase letter int firstLetter = scanner.read(); if (firstLetter == ICharacterScanner.EOF || !Character.isUpperCase( firstLetter )) { scanner.unread(); return Token.UNDEFINED; } // If this was OK, continue until we arrive to a whitespace while (true) { int nextLetter = scanner.read(); if (!Character.isJavaIdentifierPart( nextLetter )) { scanner.unread(); return tokenByTypes.get( ITokenTypes.IDENTIFIER_CONSTRUCTOR ); } } } }; rules.add(names); scanner.setRules( rules.toArray( new IRule[ rules.size() ] ) ); return scanner; } }