Github
使用递归下降语法解析,LL(k)。
其中,第一个L表示从左到右扫描输入;
第二个L表示每次都进行最左推导(在推导语法树的过程中每次都替换句型中最左的非终结符为终结符。类似还有最右推导);
k表示的是每次向前探索(lookahead)k个终结符
官网
语法文件
options {
JavaCC的选项
}
PARSER_BEGIN(解析器类名)
package 包名;
import 库名;
public class 解析器类名 {
任意的Java代码
}
PARSER_END(解析器类名)
扫描器的描述
解析器的描述
词法分析器的输入流
// 构造函数种类 ,可以接受Reader和InputStream
public class SimpleCharStream {
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize);
public SimpleCharStream(java.io.Reader dstream,
int startline, int startcolumn);
public SimpleCharStream(java.io.Reader dstream);
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException;
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize);
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException;
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn);
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException;
public SimpleCharStream(java.io.InputStream dstream);
}
Token常量,SKIP TOKEN 和TOKEN
// 忽律的字符
SKIP:{
" "
}
// 关键字
TOKEN:{
}
// 和常量申明对应
public interface XXXXXConstants {
int EOF = 0;
int PLUS = 2;
int DEFAULT = 0;
String[] tokenImage = {
// EOF 文件结尾
"" ,
// 忽律字符串
"\" \"",
// PLUSA
"\"+\"",
};
}
词法分析器
// 常见方法说明
public class XXXXXTokenManager implements XXXXXConstants {
// 输入流
protected SimpleCharStream input_stream;
// 构造函数
public XXXXXTokenManager(SimpleCharStream stream);
// 获取下一个Token
public Token getNextToken();
}
Token类
public class Token {
// Constants.java的种类
public int kind;
// 开始行和开始列,结束行和结束列
public int beginLine, beginColumn, endLine, endColumn;
// token的字符串
public String image;
// 下一个token
public Token next;
// 特殊令牌
public Token specialToken;
// Returns the image.
public String toString()
{
return image;
}
}
解析类入口
语法解析异常
语法错误提示
void S():{}
{
IFStat()
|
E();
}
void IFStat():{}
{
"if" "(" E() ")"
S()
(
"else" S();
)?
}
if E if E S else S
存在两种解释
if E
if E
S
else
S
if E
if E
S
else
S
可以借助LOOKAHEAD(K)
关键字解决
// 词法分析执行完if-S之后先找slse,找到则匹配最近的if,否则执行后面的语句
void S():{}
{
IFStat()
|
E();
}
void IFStat():{}
{
"if" "(" E() ")"
S()
(
LOOKAHEAD(1)
"else" S();
)?
}
java代码块用{}
声明
// 定义java代码块
void javaCodeDemo():
{}
{
{
int i = 0;
System.out.println(i);
}
}
需要用 JAVACODE声明
JAVACODE void print(Token t){
System.out.println(t);
}
// if语句
void ifExpr():
{}
{
[
// if - else
void ifElseExpr():
{}
{
(
{System.out.println("if else select");}
|
{System.out.println("if else update");}
|
{System.out.println("if else delete");}
|
{
System.out.println("other");
}
)
}
// while 0~n
void while1Expr():{
}
{
()*
}
// while 1~n
void while2Expr():{
}
{
()+
}
[]
: 内容可选+
: 内容出现一次或者多次*
: 内容出现0次或者多次?
: 内容出现0次或者一次|
: 或()
: 优先级改变或者整体操作mvn javacc:javacc
PARSER_BEGIN(Calculator)
package com.github.quxiucheng.parser.javacc.calc;
import java.io.* ;
public class Calculator {
public Calculator(String expr) {
this((Reader)(new StringReader(expr)));
}
public static void main(String[] args) throws Exception {
Calculator calc = new Calculator(args[0]);
System.out.println(calc.calc());
}
}
PARSER_END(Calculator)
// 忽律的字符
SKIP:{
" "
| "\t"
| "\n"
| "\r"
| "\r\n"
}
// 关键字
TOKEN:{
|
|
|
|
| "."
| "."
| "."
>
| <#DIGITS : (["0"-"9"])+ >
}
// 计算
double calc():
{
Double value ;
Double result = 0.0;
}
{
result = term()
// 加减
(
value = term()
{result += value;}
|
value =term()
{result -= value;}
)*
{return result;}
}
// 乘除
double term():
{
double value;
double result;
}
{
result = getNumber()
(
value = getNumber()
{result *= value;}
|
value = getNumber()
{result /= value;}
)*
{return result;}
}
// 获取字符串
double getNumber():
{
double number;
Token t;
}
{
t =
{number = Double.parseDouble(t.image);
return number;}
}
简单语法示例
// javacc编译设置
options {
STATIC = false;
IGNORE_CASE = true;
UNICODE_INPUT = true;
}
// 解析类
PARSER_BEGIN(JavaCCGrammar)
package com.github.quxiucheng.parser.javacc.grammar;
public class JavaCCGrammar{
public static void main(String[] args) throws Exception {
JavaCCGrammar grammar = new JavaCCGrammar(System.in);
grammar.function1();
}
}
PARSER_END(JavaCCGrammar)
// 忽律的字符
SKIP:{
" "
| "\t"
| "\n"
| "\r"
| "\r\n"
}
// token关键字
TOKEN:{
|
|
|
|
|
|
|
|
|
}
// 定义java代码块
void javaCodeDemo():
{}
{
{
int i = 0;
System.out.println(i);
}
}
// 函数
void function1():
{
// 定义局部变量
int i=0;
}
{
{return;}
}
// 返回值
double function2():
{
int i=0;
}
{
// 带返回值
{return i;}
}
// 函数调用
double function3():
{
double i;
}
{
{i = function2();}
{return i;}
}
// token复制
void tokenAssignment() :
{
Token st;
Token dt;
}
{
st =
dt =
}
// if语句
void ifExpr():
{}
{
[
{
System.out.println("if select");
}
]
// 循环,出现一次
()?
}
// if - else
void ifElseExpr():
{}
{
(
{System.out.println("if else select");}
|
{System.out.println("if else update");}
|
{System.out.println("if else delete");}
|
{
System.out.println("other");
}
)
}
// while 0~n
void while1Expr():{
}
{
()*
}
// while 1~n
void while2Expr():{
}
{
()+
}
// Java 代码
JAVACODE void print(Token t){
System.out.println(t);
}
代码示例
https://github.com/quxiucheng/apache-calcite-tutorial/tree/master/calcite-tutorial-2-parser/parser-2-javacc-tutorial