posts - 78,  comments - 48,  trackbacks - 0
Coding 生涯已经有1年4个月了,虽然比较熟悉公司框架,用起来还比较熟练,但是回头想想,其实自己还是停留在新手阶段,与刚出学校的那些“大侠”们不相上下。特别是昨天看到我们的CTO-BridGu(相信去过javaeye的朋友没有不知道这个名字的吧)给我改写的一段程序以后,感觉自己的程序是那么的幼稚。丝毫没有professional的感觉,很是惭愧!
这个功能是一个解析String生成function的功能,当然格式要求非常严格的,而且格式验证也是一个不可缺少,而且是非常重要的环节。
不知道你看到这个功能脑子里面想到是什么样的解决方案呢?我没有多想,拿起来就当String来处理,split, substring etc.

看看程序吧:
下面是我的方法,暂且说是方法吧:
 1    public void addFunction(String prototype,Long comId)throws AlpineException{
 2        ModDao dao = (ModDao)this.getDao("modDao");
 3        Components com = this.findByPrimaryKey(Components.class, comId);
 4        Functions function = new Functions();
 5        function.setComponent(com);
 6        prototype = delDupSpace(prototype);
 7        String[] funTtemp = prototype.split("\n");
 8        String fun = funTtemp[0];
 9        if(fun.indexOf("(") == -1||fun.indexOf(")") == -1){
10            throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
11        }
12        String funHead = fun.substring(0,fun.indexOf("("));
13        String[] typeAndHead = funHead.split(" ");
14        if(typeAndHead.length < 1){
15            throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
16        }else{
17            if(typeAndHead.length >1){
18                function.setReturnType(typeAndHead[0]);
19                function.setFunctionName(typeAndHead[typeAndHead.length-1]);
20            }else{
21                function.setReturnType("void");
22                function.setFunctionName(typeAndHead[0]);
23            }
24            if(fun.indexOf("//") != -1){
25                String exp = fun.substring(fun.indexOf(";")+1);
26                exp = exp.replaceAll("&#13;", "");
27                function.setExplanation(exp);
28            }
29            this.insert(function);
30    
31            String paStr = fun.substring(fun.indexOf("(")+1, fun.indexOf(")"));
32            if(!StringHelper.isEmpty(paStr)){
33                String[] pas = paStr.split(",");
34                for (int i = 0; i < pas.length; i++) {
35                    Parameters parameter = new Parameters();
36                    String[] pars = pas[i].split(" ");
37                    if(pars.length < 2 || pars.length > 3){
38                        throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
39                    }else{
40                        if(pars.length == 2){
41                            Parameters paDup = dao.getParameterByPaName(pars[1], function.getId());
42                            if(paDup != null)
43                                throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
44                                
45                            parameter.setParameterName(pars[1]);
46                            parameter.setParameterType(pars[0]);
47                            parameter.setInOrOut("In");
48                        }
49                        if(pars.length == 3){
50                            Parameters paDup = dao.getParameterByPaName(pars[2], function.getId());
51                            if(paDup != null)
52                                throw new AlpineException(ErrorCode.FUNCTION_FORMAT_ERROR);
53                            
54                            parameter.setParameterName(pars[2]);
55                            parameter.setParameterType(pars[1]);
56                            if(pars[0].contains("In"))
57                                parameter.setInOrOut("In");
58                            if(pars[0].contains("Out"))
59                                parameter.setInOrOut("Out");
60                        }
61                        parameter.setFunction(function);
62                        this.insert(parameter);
63                        parameter.setOrderF(parameter.getId());
64                        this.update(parameter);
65                    }
66                }
67            }
68            
69            for (int i = 1; i < funTtemp.length; i++) {//start 1
70                String[] paTemp = funTtemp[i].split(":");
71                if(paTemp.length == 2){
72                    Parameters parameter = dao.getParameterByPaName(paTemp[0].trim(),function.getId());
73                    if(parameter != null){
74                        parameter.setExplanation(paTemp[1]);
75                        this.update(parameter);
76                    }
77                }
78            }
79        }
80    }
以下是BirdGu的方案:
  1public class FunctionParser {
  2    public static class Token {
  3        private TokenType type;
  4        private String content;
  5        public Token(TokenType type, String content) {
  6            super();
  7            this.type = type;
  8            this.content = content;
  9        }
 10        public String getContent() {
 11            return content;
 12        }
 13        public TokenType getType() {
 14            return type;
 15        }
 16        
 17        
 18    }
 19    
 20    private enum TokenType {symbol, leftParenthese, rightParenthese, inOutFlag, comment, comma};
 21    private enum TokenParseStatus {start, inSymbol, comment1, inOutFlag};
 22
 23    private interface ParseStatus {
 24        public ParseStatus process (Functions function, Token token, Stack<String> symbolStack)
 25        throws InvalidSyntaxException;
 26    }
 27    
 28    private static final ParseStatus START = new ParseStatus() {
 29        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack)
 30        throws InvalidSyntaxException {
 31            if (token.getType() == TokenType.symbol) {
 32                symbolStack.push(token.getContent());
 33                return GOT_FIRST_SYMBOL;
 34            } 
 35            throw new InvalidSyntaxException (token);
 36        }
 37    };
 38    
 39    private static final ParseStatus GOT_FIRST_SYMBOL = new ParseStatus () {
 40        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 41            if (token.getType() == TokenType.leftParenthese) {
 42                function.setReturnType("void");
 43                function.setFunctionName(symbolStack.pop());
 44                return WAITING_FIRST_ARG;
 45            } else if (token.getType() == TokenType.symbol) {
 46                function.setFunctionName(token.getContent());
 47                function.setReturnType(symbolStack.pop());
 48                return BEFORE_ARG_DEF;
 49            } 
 50            throw new InvalidSyntaxException (token);
 51        }
 52    };
 53    
 54    private static final ParseStatus BEFORE_ARG_DEF = new ParseStatus () {
 55        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 56            if (token.getType() == TokenType.leftParenthese) {
 57                return WAITING_FIRST_ARG;
 58            }
 59            throw new InvalidSyntaxException (token);
 60        }
 61    };
 62    
 63    private static final ParseStatus WAITING_FIRST_ARG = new ParseStatus () {
 64
 65        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 66            if (token.getType() == TokenType.rightParenthese) {
 67                return AFTER_ARG_DEF;
 68            } else if (token.getType() == TokenType.symbol) {
 69                symbolStack.push(token.getContent());
 70                return GOT_ARG_TYPE;
 71            } else if (token.getType() == TokenType.inOutFlag) {
 72                symbolStack.push (token.getContent());
 73                return GOT_IN_OUT_FLAG;
 74            }
 75            throw new InvalidSyntaxException (token);    
 76        }
 77    };
 78    
 79    private static final ParseStatus GOT_IN_OUT_FLAG = new ParseStatus () {
 80        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 81            if (token.getType() == TokenType.symbol) {
 82                symbolStack.push(token.getContent());
 83                return GOT_ARG_TYPE;
 84            }
 85            throw new InvalidSyntaxException (token);    
 86        }
 87    };
 88    
 89    private static final ParseStatus GOT_ARG_TYPE = new ParseStatus () {
 90        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
 91            if (token.getType() == TokenType.symbol) {
 92                Parameters param = new Parameters ();
 93                param.setParameterName(token.getContent());
 94                param.setParameterType(symbolStack.pop());
 95                String inOutFlag = "In";
 96                if (!symbolStack.isEmpty()) {
 97                    inOutFlag = symbolStack.pop();
 98                }
 99                param.setInOrOut(inOutFlag);
100                function.adParameter(param);
101                return GOT_ARG_VALUE;
102            }
103            throw new InvalidSyntaxException (token);    
104        }
105    };
106    
107    private static final ParseStatus GOT_ARG_VALUE = new ParseStatus () {
108        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
109            if (token.getType() == TokenType.rightParenthese) {
110                return AFTER_ARG_DEF;
111            } else if (token.getType() == TokenType.comma) {
112                return WAITING_ARG;
113            }
114            throw new InvalidSyntaxException (token);    
115        }
116    };
117    
118    private static final ParseStatus WAITING_ARG = new ParseStatus () {
119        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
120            if (token.getType() == TokenType.symbol) {
121                symbolStack.push(token.getContent());
122                return GOT_ARG_TYPE;
123            } else if(token.getType() == TokenType.inOutFlag) {
124                symbolStack.push(token.getContent());
125                return GOT_IN_OUT_FLAG;
126            }
127            return null;
128        }
129    };
130    
131    private static final ParseStatus AFTER_ARG_DEF = new ParseStatus () {
132        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
133            if (token.getType() == TokenType.comment) {
134                function.setExplanation(token.getContent());
135                return END;
136            }
137            throw new InvalidSyntaxException (token);
138        }
139    };
140    
141    private static final ParseStatus END = new ParseStatus () {
142        public ParseStatus process(Functions function, Token token, Stack<String> symbolStack) throws InvalidSyntaxException {
143            throw new InvalidSyntaxException (token);
144        }
145    };
146    
147    private StringBuffer currentLine;
148    private int index;
149    private Functions function;
150    
151    public Functions parse(String content) throws InvalidSyntaxException {
152        if (StringHelper.isEmpty(content)) {
153            throw new IllegalArgumentException ("content is empty.");
154        }
155        StringTokenizer tokenizer = new StringTokenizer (content, "\n");
156        String line = tokenizer.nextToken();
157        parseFirstLine (line);
158        while (tokenizer.hasMoreTokens()) {
159            line = tokenizer.nextToken();
160            parseParamLine (line);
161        }
162        return function;
163    }
164    
165    private void parseFirstLine (String line) throws InvalidSyntaxException {
166        currentLine = new StringBuffer (line);
167        index = 0;
168        function = new Functions ();
169        Token token;
170        ParseStatus status = START;
171        Stack<String> stack = new Stack<String> ();
172        while ( (token = nextToken()) != null) {
173            status = status.process(function, token, stack);
174        }
175        if (status != AFTER_ARG_DEF && status != END) 
176            throw new InvalidSyntaxException ("Function hasn't finished properly.");
177    }
178
179    private void parseParamLine (String line) 
180    throws InvalidSyntaxException {
181        int idx = line.indexOf(':');
182        if (idx < 0) {
183            throw new InvalidSyntaxException ("Expected ':' from parameter line.");
184        }
185        String paramName = line.substring(0, idx);
186        String comment = line.substring(idx + 1);
187        Parameters param = function.getParameter (paramName);
188        if (paramName == null)
189            throw new InvalidSyntaxException ("Unknown parameter:'paramName'");
190        param.setExplanation(comment);
191    }
192    
193    private Token nextToken () throws InvalidSyntaxException {
194        if (index >= currentLine.length())
195            return null;
196        StringBuffer buf = new StringBuffer ();
197        TokenParseStatus status = TokenParseStatus.start;
198        while (index < currentLine.length ()) {
199            char ch = currentLine.charAt(index);
200            if (status == TokenParseStatus.start) {
201                if (isSymbolLetter(ch)) {
202                    status = TokenParseStatus.inSymbol;
203                    buf.append(ch);
204                    ++ index;
205                } else if (ch == '(') {
206                    ++ index;
207                    return new Token (TokenType.leftParenthese, "(");
208                } else if (ch == ')') {
209                    ++ index;
210                    return new Token (TokenType.rightParenthese, ")");
211                } else if (ch == ',') {
212                    ++ index;
213                    return new Token (TokenType.comma, ",");
214                } else if (ch == ' ' || ch == '\t') {
215                    ++ index;
216                } else if (ch == '[') {
217                    status = TokenParseStatus.inOutFlag;
218                    ++ index;
219                } else if (ch == ';') {
220                    ++ index;
221                    String str = currentLine.substring(index);
222                    index = currentLine.length();
223                    return new Token (TokenType.comment, str);
224                } else {
225                    throw new InvalidSyntaxException ("Enexpected character: " + ch);
226                }
227            } else if (status == TokenParseStatus.inSymbol) {
228                if (isSymbolLetter(ch)) {
229                    buf.append(ch);
230                    ++ index;
231                } else {
232                    return new Token (TokenType.symbol, buf.toString());
233                } 
234            } else if (status == TokenParseStatus.inOutFlag) {
235                if (isSymbolLetter(ch)) {
236                    buf.append (ch);
237                    ++ index;
238                } else if ( ch == ']') {
239                    ++ index;
240                    String str = buf.toString ();
241                    if (! ("In".equals(str) || "Out".equals(str))) {
242                        throw new InvalidSyntaxException ("Invalid in/out flag.");
243                    }
244                    return new Token (TokenType.inOutFlag, str);
245                }
246            }
247        }
248        if (status == TokenParseStatus.inSymbol) {
249            return new Token (TokenType.symbol, buf.toString());
250        }
251        return null;
252    }
253
254    private boolean isSymbolLetter(char ch) {
255        return Character.isLetter(ch) || Character.isDigit(ch);
256    }
257}

相比之下,第一种方法相形见绌。
想必这也是很多“大鸟”找不到合适人选的原因吧。
上面两种方法不用多说,大家一看就知道好在哪里,同时还是编程思想的截然不同。
posted on 2006-12-01 10:13 黑咖啡 阅读(409) 评论(0)  编辑  收藏 所属分类: Coding LifeCoding Review

只有注册用户登录后才能发表评论。


网站导航:
 

<2006年12月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

留言簿(2)

随笔分类(67)

文章分类(43)

Good Article

Good Blogs

Open Source

最新随笔

最新评论

阅读排行榜

评论排行榜