引用
使用 Antlr 处理文本
https://www.ibm.com/developerworks/cn/java/j-lo-antlrtext/index.html
该文章写的非常好,无耐是2011年写的,与现有的antlr版本差别较大,编译不过去,编译过去,也测试不出来正确的结果,以下为用antlr4.2重写的
新项目使用maven和ant构建,需要以下几个文件
- pom.xml
- build.xml
- SqlExtrator.g4语法文件
- SqlExtrator.clj测文件
- Test.java 测试代码
测试方法,
- 先用ant执行compile任务,生成和编译生成的一堆词法解析器和语法解析器代码, 然后执行ant的 test任务,解析 SqlExtrator.clj测文件里的文本
- 使有Test.java,手动编程调用
使用ant任务的截图,
pom.xml
4.0.0 com.xxx.lang fieldTypeUpdate 0.0.1-SNAPSHOT jar fieldTypeUpdate http://maven.apache.org UTF-8 junit junit 3.8.1 test org.antlr antlr4 4.2 org.codehaus.mojo build-helper-maven-plugin 1.8 add-source generate-sources add-source
build.xml
SqlExtrator.g4 语法文件 该语法文件,仅可以识别词法规定的字符,词法外的字符将会报错
grammar SqlExtrator; WS : (' ' |'\t' |'\r' |'\n' )+ ; INT: '0'..'9' + ; ID : ('a'..'z' |'A'..'Z' |'_' ) ('a'..'z' |'A'..'Z' |'_' |'0'..'9' )*; EOL: ('\n' | '\r' | '\r\n')*; SUCCESS:'DB20000I The SQL command completed successfully.'EOL ; SqlFrg :'INSERT INTO SYSA.' ID '(' ID ',' ID ')' WS 'VALUES' '(\'' ID '\',\'' INT '\')'EOL ; txt:mysql=SqlFrg {System.out.println($mysql.text);} SUCCESS; sql:(txt)+;
第二个版本的语法,添加了:
FILTER: .? -> skip;
仅这一行,这行代码,使用正则的非贪婪匹配规则,
引用
Wildcard Operator and Nongreedy Subrules
正则表达式贪婪与非贪婪模式
1.什么是正则表达式的贪婪与非贪婪匹配
如:String str="abcaxc";
Patter p="ab.*c";
贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab.*c)。
非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab.*c)。
2.编程中如何区分两种模式
默认是贪婪模式;在量词后面直接加上一个问号?就是非贪婪模式。
量词:{m,n}:m到n个
*:任意多个
+:一个到多个
?:0或一个
grammar SqlExtrator; SqlFrg :'INSERT INTO SYSA.' ID '(' ID ',' ID ')' WS 'VALUES' '(\'' ID '\',\'' INT '\')' ; fragment WS : (' ' |'\t' |'\r' |'\n' )+ ; fragment ID: ('a'..'z' |'A'..'Z' |'_' ) ('a'..'z' |'A'..'Z' |'_' |'0'..'9' )*; fragment INT: '0'..'9' + ; fragment EOL: '\n' | '\r' | '\r\n'; SUCCESS:'DB20000I The SQL command completed successfully.' ; all: (SqlFrg SUCCESS {System.out.println($SqlFrg.text);})+ ; FILTER: .? -> skip;
SqlExtrator.clj 测试文件
INSERT INTO SYSA.IF_EMPUSRRLA(USRNUM,EMPNUM) VALUES('U037508','275159') DB20000I The SQL command completed successfully. document.write(v+' test is '+result+'');//该行代码在第一个版本的语法中会报错 INSERT INTO SYSA.IF_USRSTNRLA(USRNUM,STNNUM) VALUES('U037710','00026') DB20000I The SQL command completed successfully.
Test.java 测试代码
public class Test { public static void main(String[] args) { try { String filename = "D:\\workplace\\fieldTypeUpdate\\src\\test\\java\\SqlExtrator.clj"; InputStream in = new FileInputStream(filename); ANTLRInputStream input = new ANTLRInputStream(in); SqlExtratorLexer lexer = new SqlExtratorLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); SqlExtratorParser parser = new SqlExtratorParser(tokens); parser.sql(); System.out.println("done!"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
测试结果控制台输出:
引用
INSERT INTO SYSA.IF_EMPUSRRLA(USRNUM,EMPNUM) VALUES('U037508','275159')
INSERT INTO SYSA.IF_USRSTNRLA(USRNUM,STNNUM) VALUES('U037710','00026')
done!