/**
* <p>Copyright: Copyright (c) 2012</p>
* <p>Company: �������ӹɷ�����˾</p>
*/
package com.hundsun.ares.studio.engin.parser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import com.hundsun.ares.studio.engin.constant.IEngineContextConstant;
import com.hundsun.ares.studio.engin.token.CodeTokenFactory;
import com.hundsun.ares.studio.engin.token.ICodeToken;
/**
* @author qinyuan
*
*/
public class PseudoCodeParser implements IPseudocodeParser{
public static final int CPP_TYPE = 0;//ʹ��cppע��
public static final int PROC_TYPE = 1;//ʹ��procע��
/**
* ����ע�ͱ��
*/
public static String functionRemark = "//";
/** C��ע��������ʽ */
public static Pattern CPP_COMMENT_PATTERN = Pattern.compile("(//[^\\r\\n]+((\\r?\\n)|$))|(/\\*.*?\\*/)", Pattern.DOTALL);
/** plsql��ע��������ʽ */
public static Pattern PROC_COMMENT_PATTERN = Pattern.compile("(--[^\\r\\n]+((\\r?\\n)|$))|(/\\*.*?\\*/)", Pattern.DOTALL);
/** C���ַ�������ʽ */
//Pattern.compile("\"((\\\\\")|([^\"]))*\"") ԭ����ƥ�䳤�ַ�����ʱ��Ỻ�������
public static Pattern CPP_STRING_PATTERN = Pattern.compile("\"[^\"]*\"");
/** plsql���ַ�������ʽ */
public static Pattern PROC_STRING_PATTERN = Pattern.compile("'[^']*'");
/* (non-Javadoc)
* @see com.hundsun.ares.studio.uft.engin.parser.IPseudocodeParser#parse(java.lang.String, java.util.Map)
*/
@Override
public Iterator<ICodeToken> parse(String pseudocode,int commentType,
Map<Object, Object> context) throws Exception {
if(commentType == PROC_TYPE) {
return parseEx(pseudocode, PROC_COMMENT_PATTERN, PROC_STRING_PATTERN,context);
}else {
return parseEx(pseudocode, CPP_COMMENT_PATTERN, CPP_STRING_PATTERN,context);
}
}
/**
*
* �ֽ�Դ����Ϊ�ꡢ�ı���ע�͡��ַ���4������
* ��Ŀǰ��Ҫ��һ�е����ף���Ȼǰ������пհ��ַ�����tab space
*
* @param pseudocode ���
* @param pComment �����ʹ���ʹ�õ�ע�����͵�����ʽ
* @param pString �����ʹ���ʹ�õ��ַ���������ʽ
* @return
*/
public static Iterator<ICodeToken> parseEx(String pseudocode, Pattern pComment, Pattern pString,Map<Object, Object> context) {
List<Pattern> patterns = new ArrayList<Pattern>();
Pattern patternComment = pComment; //
// һ�п�ͷ�������пհ��ַ��������б�־λ��[]���ݵ�1������
Pattern patternMacro = Pattern.compile("(^[ \\t]*(<[A-Za-z]+>)?(\\[(('[^']*')|(\"((\\\\\")|([^\"]))*\")|([^\\]\\[]*))\\])+)", Pattern.MULTILINE);
patterns.add(patternComment);
patterns.add(pString);
patterns.add(patternMacro);
List<SourcePartition> patitions = new ArrayList<SourcePartition>();
doPartition(0, 0, pseudocode, patterns, patitions);
List<ICodeToken> codes = new ArrayList<ICodeToken>();
if(!context.containsKey(IEngineContextConstant.PSEUDO_CODE_PARA_LIST)){
context.put(IEngineContextConstant.PSEUDO_CODE_PARA_LIST, new ArrayList<String>(){
/* (non-Javadoc)
* @see java.util.ArrayList#add(java.lang.Object)
*/
@Override
public boolean add(String arg0) {
if(!contains(arg0)){
return super.add(arg0);
}
return false;
}
});
}
//α�������õ��Ķ���α�����б�
if(!context.containsKey(IEngineContextConstant.PSEUDO_CODE_OBJECT_PARA_LIST)){
context.put(IEngineContextConstant.PSEUDO_CODE_OBJECT_PARA_LIST, new ArrayList<String>(){
/* (non-Javadoc)
* @see java.util.ArrayList#add(java.lang.Object)
*/
@Override
public boolean add(String arg0) {
if(!contains(arg0)){
return super.add(arg0);
}
return false;
}
});
}
for (SourcePartition sourcePartition : patitions) {
ICodeToken code = null;
String sourceText = sourcePartition.getText();
List<String> paramList = new ArrayList<String>();
boolean findResultSetStr = false;
if (!patternComment.equals(sourcePartition.getPattern()) &&
!pString.equals(sourcePartition.getPattern())){//�ַ�����Ҳ��Ӧ�����
//ע�Ͳ��ý��ͱ��ֶ�
List<String> PseudoParaList = (List<String>)context.get(IEngineContextConstant.PSEUDO_CODE_PARA_LIST);
List<String> pseudoObjectParaList = (List<String>)context.get(IEngineContextConstant.PSEUDO_CODE_OBJECT_PARA_LIST);
for (String fld : CodeParserUtil.findStandardField(sourceText)) {
paramList.add(fld);
//�Ѵ����˾Ͳ����
if(!StringUtils.endsWith(fld, "ResultSet")){
PseudoParaList.add(fld);
}else{
if(StringUtils.endsWith(fld, "ResultSet")){
int index = StringUtils.lastIndexOf(fld, "ResultSet");
String relName = StringUtils.substring(fld, 0,index);
pseudoObjectParaList.add(relName);
}
}
}
//�ı��д���ResultSet->
findResultSetStr = CodeParserUtil.findResultSetStr(sourceText);
}
if (sourcePartition.getPattern() == null) {
//ResultSet->�϶�������Proc������ʹ�ã��ʿ϶�����Ҫ��TextWithParamsToken
if(findResultSetStr){
code = CodeTokenFactory.getInstance().createResultSetToken(sourceText);
}else if(paramList.isEmpty()){// ��ͨ�ı�
code = CodeTokenFactory.getInstance().createCodeTextToken(sourceText);
}else{
code = CodeTokenFactory.getInstance().createTextWithParamsToken(sourceText, paramList);
}
codes.add(code);
} else if (sourcePartition.getPattern().equals(patternComment)) {
// ע��
code = CodeTokenFactory.getInstance().createCommentToken(sourceText);
codes.add(code);
} else if (sourcePartition.getPattern().equals(pString)) {
// �ַ���
// if(paramList.isEmpty()){
// code = CodeTokenFactory.getInstance().createCodeTextToken(sourceText);
// }else{
// code = CodeTokenFactory.getInstance().createTextWithParamsToken(sourceText, paramList);
// }
code = CodeTokenFactory.getInstance().createStringToken(sourceText);
codes.add(code);
} else if (sourcePartition.getPattern().equals(patternMacro)) {
// ��
code = CodeTokenFactory.getInstance().createMacroToken(sourceText,sourcePartition.getLineNum());
codes.add(code);
}
}
return codes.iterator();
}
/**
* ��ȡ����
* @param originalText
* @return
*/
private static String getMacroID(String originalText) {
String keyword;
String trim = originalText.trim();
if(trim.isEmpty()){
return "";
}
String s[] = trim.substring(trim.indexOf("[") + 1, trim.length() - 1).split("\\]\\[");
keyword = s[0];
return keyword;
}
/**
* ���ݸ�����������ʽ��ֽ��ַ��������������˳�������ڲ���List��˳����
*
* @param nStartLine
* @param source
* @param patterns
* @param patitions
*/
protected static void doPartition(int nStartLine, int nStart, String source, List<Pattern> patterns, List<SourcePartition> patitions) {
patitions.addAll(doPartition(source, patterns));
}
protected static List<SourcePartition> doPartition(String source, List<Pattern> patterns) {
int pos = 0;
int nStartLine = 0;
int length = source.length();
List<SourcePartition> partitions = new ArrayList<SourcePartition>();
while (pos < length) {
String subSource = source.substring(pos);
Matcher m = getFirstMatch(subSource, patterns);
if (m == null) {
partitions.add(new SourcePartition(subSource, nStartLine, pos, length - pos, null));
break;
} else {
MatchResult result = m.toMatchResult();
if (result.start() == 0) {
String matchText = result.group();
partitions.add(new SourcePartition(matchText, nStartLine, pos, result.end() - result.start(), m.pattern()));
nStartLine += getLFCount(matchText);
} else {
// ǰ��δƥ��IJ���
String notMatchText = subSource.substring(0, result.start());
partitions.add(new SourcePartition(notMatchText, nStartLine, pos, pos + result.start() - 1, null));
// ����ĿǰӦ��Ϊ�ڼ���
nStartLine += getLFCount(notMatchText);
String matchText = result.group();
partitions.add(new SourcePartition(matchText, nStartLine, pos + result.start(),
result.end() - result.start(), m.pattern()));
nStartLine += getLFCount(matchText);
}
pos += result.end();
}
}
return partitions;
}
/**
* ���֮�������
*
* @param content
* @return
*/
private static int getLFCount(String content) {
//2011��8��3��15:26:57 ���������ʹ�ã�����ƥ���ַ����࣬��ջ�����
int count = 0;
for (char c : content.toCharArray()) {
if (c == '\n') {
count++;
}
}
return count;
}
/**
* �������������ƥ��,ȡ������ƥ���ƥ����
*
* @param source
* @param patterns
* @return
*/
private static Matcher getFirstMatch(String source, List<Pattern> patterns) {
Matcher result = null;
int i = 0;
// ���ҵ�һ��ƥ���
for (; i < patterns.size(); i++) {
Matcher m = patterns.get(i).matcher(source);
if (m.find()) {
result = m;
break;
}
}
// ����һ������ƥ���ƥ����
for (; i < patterns.size(); i++) {
Matcher m = patterns.get(i).matcher(source);
if (m.find()) {
if (m.start() < result.start()) {
result = m;
}
}
}
return result;
}
// public static List<String> parserVariables(String pseudocode) {
//
// // ���ȷֽ��ע��
// List<ICodeToken> codes = parseEx(pseudocode);
// List<String> ret = new LinkedList<String>();
//
// for (ICodeToken code : codes) {
// if (code instanceof TextCode) {
// Pattern p = Pattern.compile("@[\\w\\d_]+");
// Matcher m = p.matcher(code.toString());
// while (m.find()) {
// ret.add(m.group().substring(1));
// }
// }
// }
// return ret;
// }
public static void main(String[] args) {
// ��ȡ�ļ�
StringBuffer trueCode = new StringBuffer();
try {
FileReader fr = new FileReader(new File("D:\\test\\test.txt"));
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
trueCode.append(line);
line = br.readLine();
if (line != null) {
trueCode.append("\n");
}
}
br.close();
fr.close();
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("//////////Դ�ļ�///////////////////");
System.out.println(trueCode.toString());
System.out.println("//////////�������ļ�/////////////////////");
Map<Object, Object> context = new HashMap<Object, Object>();
// Iterator<ICodeToken> parseredCode = parseEx(trueCode.toString(), CPP_COMMENT_PATTERN, CPP_STRING_PATTERN,context);
// int i = 1;
// while (parseredCode.hasNext()) {
// ICodeToken t = parseredCode.next();
// System.out.println("��" + i +"��������: \n");
// System.out.println(t.getContent());
// i++;
// }
// List<String> stdflds = (List<String>)context.get(IEngineContextConstant.PSEUDO_CODE_PARA_LIST);
// System.out.println(stdflds);
Map<String, String> ret = parserKeyValue(trueCode.toString());
for (String string : ret.keySet()) {
System.out.println("key is :" + string+", value is :" + ret.get(string));
}
}
/**
* �������������
* @param s
* @return
*/
public static Map<String, String> parserKeyValue(String s) {
Map<String, String> ret = new Hashtable<String, String>();
Pattern p = Pattern.compile("(@?[\\w\\d_]+(\\s*)=(\\s*)@?(('.*?')|([^,]*)))");
Pattern p2 = Pattern.compile("(@?(\\s)*=@?(\\s*))");
Matcher m = p.matcher(s);
while (m.find()) {
String result = m.group();
Matcher m2 = p2.matcher(result);
m2.find();
ret.put(result.substring(0, m2.start()), result.substring(m2.end()));
}
return ret;
}
/**
* �������������
* �ֽ�ʱ����value��@����
*
*/
public static Map<String, String> parserKeyValueWithAt(String s) {
Map<String, String> ret = new Hashtable<String, String>();
Pattern p = Pattern.compile("(@?[\\w\\d_]+(\\s*)=(\\s*)@?(('.*?')|(\".*?\")|([^,]*)))");
//("(@?[\\w\\d_]+(\\s*)=(\\s*)@?(('.*?')|([^,]*)))");
Pattern p2 = Pattern.compile("((\\s)*=(\\s*))");
Matcher m = p.matcher(s);
while (m.find()) {
String result = m.group();
Matcher m2 = p2.matcher(result);
m2.find();
ret.put(result.substring(0, m2.start()).trim(), result.substring(m2.end()).trim());
}
return ret;
}
/**
* ����ע��
* @param str
* @param replace
* @return
*/
public static String insertCommonForSql(String str,String replace){
replace = "/*"+replace + "*/";
return str.replaceAll("\\bselect\\b", "select"+replace)
.replaceAll("\\bSELECT\\b", "SELECT"+replace)
.replaceAll("\\bupdate\\b", "update"+replace)
.replaceAll("\\bUPDATE\\b", "UPDATE"+replace)
.replaceAll("\\binsert into\\b", "insert into"+replace)
.replaceAll("\\bINSERT INTO\\b", "INSERT INTO"+replace)
.replaceAll("\\bdelete\\b", "delete"+replace)
.replaceAll("\\bDELETE\\b", "DELETE"+replace);
}
}