1 6 package tests.jfun.parsec.coloring; 7 import java.util.HashMap ; 8 9 import jfun.parsec.Tokenizer; 10 import jfun.parsec.pattern.Pattern; 11 import jfun.parsec.pattern.Patterns; 12 import jfun.parsec.DefaultPositionMap; 13 import jfun.parsec.Lexers; 14 import jfun.parsec.Scanners; 15 import jfun.parsec.Parser; 16 import jfun.parsec.Parsers; 17 22 final class JavaFormatter { 23 private final String [] keywords = { 24 "if","else","this","private","static","public", 25 "protected","final","interface","class","abstract", 26 "extends","implements", 27 "import", "package", "for","while","do", 28 "switch","case","break","continue", 29 "return","default","super","new", 30 "try","catch","finally","throw","throws","const"}; 31 private final char[] ops = {'+','-','*','/','%', 32 '|','&','>','<','=',';',',','.','?',':','!','^','(',')','[',']', 33 '{','}','~','@','#','\\','`'}; 34 private final char[] delimiters = {'+','-','*','/','%', 35 '|','&','>','<','=',';',',','.','?',':','!','^','(',')','[',']', 36 '{','}','~',' ', '\t', '\r','\n','`','\\','@','#'}; 37 private final String [] natives = {"int","long","char","short","boolean"}; 38 private final String [] stds = {"String","Integer","Long","Short","Character","Boolean","finalize"}; 39 private static HashMap toMap(String [] words){ 40 final HashMap ret = new HashMap (); 41 for(int i=0; i<words.length; i++){ 42 ret.put(words[i], words[i]); 43 } 44 return ret; 45 } 46 private final HashMap keywords_map = toMap(keywords); 47 private final HashMap natives_map = toMap(natives); 48 private final HashMap stds_map = toMap(stds); 49 50 private static final Object nil_token = new Object (); 51 private Tokenizer getOpTokenizer(final CodeStream stream){ 52 return new Tokenizer(){ 53 public Object toToken(final CharSequence cs, final int from, final int len){ 54 stream.addOperator(cs, from, len); 55 return nil_token; 56 } 57 }; 58 } 59 private Tokenizer getCommentTokenizer(final CodeStream stream){ 60 return new Tokenizer(){ 61 public Object toToken(final CharSequence cs, final int from, final int len){ 62 stream.addComment(cs, from, len); 63 return nil_token; 64 } 65 }; 66 } 67 private Tokenizer getWhitespaceTokenizer(final CodeStream stream){ 68 return new Tokenizer(){ 69 public Object toToken(final CharSequence cs, final int from, final int len){ 70 stream.addWhitespace(cs, from, len); 71 return nil_token; 72 } 73 }; 74 } 75 private Tokenizer getStringTokenizer(final CodeStream stream){ 76 return new Tokenizer(){ 77 public Object toToken(final CharSequence cs, final int from, final int len){ 78 stream.addStringLiteral(cs, from, len); 79 return nil_token; 80 } 81 }; 82 } 83 private Tokenizer getCharTokenizer(final CodeStream stream){ 84 return new Tokenizer(){ 85 public Object toToken(final CharSequence cs, final int from, final int len){ 86 stream.addCharLiteral(cs, from, len); 87 return nil_token; 88 } 89 }; 90 } 91 private Tokenizer getNumTokenizer(final CodeStream stream){ 92 return new Tokenizer(){ 93 public Object toToken(final CharSequence cs, final int from, final int len){ 94 stream.addNumberLiteral(cs, from, len); 95 return nil_token; 96 } 97 }; 98 } 99 private Tokenizer getWordTokenizer(final CodeStream stream){ 100 return new Tokenizer(){ 101 public Object toToken(final CharSequence cs, final int from, final int len){ 102 final String str = cs.subSequence(from, from+len).toString(); 103 if(keywords_map.containsKey(str)){ 104 stream.addKeyword(cs, from, len); 105 } 106 else if(natives_map.containsKey(str)){ 107 stream.addNativeWord(cs, from, len); 108 } 109 else if(stds_map.containsKey(str)){ 110 stream.addStandardWord(cs, from, len); 111 } 112 else stream.addRegular(cs, from, len); 113 return nil_token; 114 } 115 }; 116 } 117 118 119 private Parser getLexer(final CodeStream stream){ 120 final Parser isInteger = Scanners.isPattern( 121 Patterns.or( 122 Patterns.isHexInteger(), 123 Patterns.isOctInteger(), 124 Patterns.isDecInteger() 125 ).seq(Patterns.among(new char[]{'l','L'}).optional()), 126 "integer literal" 127 ); 128 final Parser isDecimal = Scanners.isPattern(Patterns.isDecimal(), "decimal"); 129 final Pattern word_char = Patterns.notAmong(delimiters); 130 final Parser numLiteral = Parsers.longer(isDecimal, isInteger) 131 .seq(Scanners.isPattern(Patterns.isExponential().optional() 132 .seq(word_char.not()), "number literal" 133 ) 134 ); 135 final Parser word_lexer = Lexers.lexer(Scanners.isPattern(word_char.many1(), "word"), 136 getWordTokenizer(stream)); 137 final Parser op_lexer = Lexers.lexer(Scanners.among(ops).many1(), 138 getOpTokenizer(stream)); 139 final Parser comment_lexer = Lexers.lexer(Parsers.sum(Scanners.javaBlockComment(), Scanners.javaLineComment()), 140 getCommentTokenizer(stream)); 141 final Parser str_lexer = Lexers.lexer(Scanners.isQuotedString(), 142 getStringTokenizer(stream)); 143 Pattern any_chr = Patterns.hasAtLeast(1); 144 Pattern single_quote = Patterns.isChar('\''); 145 Pattern ptn_chr = 146 149 Patterns.regex("'((\\.)|.)'"); 150 final Parser char_lexer = 151 Lexers.lexer(Scanners.isPattern(ptn_chr, 152 "character literal"), 153 getCharTokenizer(stream)); 154 final Parser num_lexer = Lexers.lexer(numLiteral, 155 getNumTokenizer(stream)); 156 final Parser space_lexer = Lexers.lexer(Scanners.isWhitespaces(), 157 getWhitespaceTokenizer(stream)); 158 return Parsers.sum(new Parser[]{ 159 space_lexer, comment_lexer, 160 op_lexer, 161 str_lexer, char_lexer, 162 num_lexer, word_lexer 163 }).many(); 164 } 165 public void format(final CharSequence src, 166 final CodeStream stream){ 167 final Parser lx = getLexer(stream); 168 Parsers.runParser(src, lx, 169 new DefaultPositionMap(src, 1, 1), "java formatter"); 170 } 171 } 172 | Popular Tags |