最近尝试使用 corenlp
做数据抽取工作,发现其中使用 JavaCC
进行文本操作。
JavaCC
是一个词法分析生成器和语法分析生成器。词法分析和语法分析是处理输入字符序列的软件组件,编译器和解释器协同词法分析和语法分析来解码程序文件。词法分析器可以把一连串的字符序列划分成一个一个的叫做 Token
的子序列,同时它也可以把这些 Token
分类。这些 Token
序列将会传送给语法分析器以供其决定程序的结构。
JavaCC
的输入文件是一个词法和语法的规范文件,其中也包括一些动作的描述,它的后缀应该是 *.jj
。
先来个基础样例:
//**
* 设定选项参数
*/
//options {
// LOOKAHEAD = 1; // 预读 token 数量
// STATIC = false; // 是否生成静态函数
// UNICODE_INPUT = true; // 是否使用 Unicode 输入
// DEBUG_PARSER = false; // 是否输出调试信息
//}
/**
* 定义解析类, 由
* PARSER_BEGIN (类名)
* ...正文...
* PARSER_END (类名)
* 来构成主类之间的主函数 main 实现
*/
PARSER_BEGIN (Calc)
package calc;
import java.io.*;
/**
* Macro statements are as follows :
* <List> ::= { <E> "=" }
* <E> ::= <T> { ( "+" <T> ) | ( "-" <T> ) }
* <T> ::= <F> { ( "*" <F> ) | ( "/" <F> ) | ( "%" <F> ) }
* <F> ::= ( "(" <E> ")" ) | INTEGER
* Execute as follows :
* $ javac Calc.java
* $ java Calc [inputfile]
*/
public class Calc {
public static void main (String args[]) {
Calc parser;
try {
if (args.length == 0) {
parser = new Calc (System.in);
} else {
parser = new Calc (new FileReader (args[0]));
}
parser.enable_tracing();
parser.List();
} catch (Exception err_mes) {
System.err.println (err_mes);
}
}
}
PARSER_END (Calc)
/**
* 定义空白字符及字符串
* 空白字符以
* SKIP :
* {
* <模板>
* }
* 的形式进行定义,模板内容可为正则表达式。
*/
SKIP :
{
< " " | "\t" | "\n" | "\r" >
}
/**
* 定义 token 类型
* Token 的形式如下:
* TOKEN :
* {
* <Token 名称/类型: 模板>
* }
* 的形式进行定义,模板内容可为正则表达式。
*/
TOKEN : {
<INTEGER: (["0"-"9"])+>
}
/**
* 实现执行赋值表达式
* <List> ::= { <E> "=" }
* void parseList() {
* int value;
* while (true) {
* value = parseE();
* if (token == "=")
* System.out.println (value);
* }
* }
*/
void List() :
{ int value; }
{
(
value = E()
"=" { System.out.println (value); }
)*
}
/**
* 实现基础运算表达式
* <E> ::= <T> { ( "+" <T> ) | ( "-" <T> ) }
* void parseE() {
* int result1, result2;
* result1 = parseT();
* while (token == "+" || token == "-") {
* if (token == "+") {
* result2 = parseT();
* result1 += result2;
* } else if (token == "-") {
* result2 = parseT();
* result1 -= result2;
* }
* return result1;
* }
*/
int E() :
{ int result1, result2; }
{
result1 = T()
(
"+" result2 = T() { result1 += result2; }
| "-" result2 = T() { result1 -= result2; }
)*
{ return result1; }
}
/**
* 实现 乘 除 余 运算表达式
* <T> ::= <F> { ( "*" <F> ) | ( "/" <F> ) | ( "%" <F> )}
* void parseT() {
* int result1, result2;
* result1 = parseF();
* while (token == "*" || token == "/" || token == "%") {
* if (token == "*") {
* result2 = parseF();
* result1 *= result2;
* } else if (token == "/") {
* result2 = parseF();
* result1 /= result2;
* } else if (token == "%") {
* result2 = parseF();
* result1 %= result2;
* }
* return result1;
* }
*/
int T() :
{ int result1, result2; }
{
result1 = F()
(
"*" result2 = F() { result1 *= result2; }
| "/" result2 = F() { result1 /= result2; }
| "%" result2 = F() { result1 %= result2; }
)*
{ return result1; }
}
/**
* 实现 括号 运算表达式
* <F> ::= ( "(" <E> ")" ) | INTEGER
* void parseF() {
* int result;
* if (token == "(") {
* nextToken();
* result = parseE();
* if (token == ")") nextToken();
* return result;
* } else if (token == INTEGER) {
* return token.getValue();
* }
* }
*/
int F():
{ int result; }
{
"(" result = E() ")" { return result; }
| token = <INTEGER> { return Integer.parseInt (token.image); }
}
参考
网友评论