|
![]() |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
javaCC的功能和yacc相似,主要根据bnf范式生成解析程序,不过javaCC是集合了词法分析和语法分析生成java解析代码,主页为:https://javacc.dev.java.net/ javaCC有三个工具 javaCC 用来处理语法文件(jj)生成解析代码; jjTree 用来处理jjt文件,生成树节点代码和jj文件,然后再通过javaCC生成解析代码; jjDoc 根据jj文件生成bnf范式文档(html) javaCC使用的各种语言的Grammar 文件这里有很多http://www.cobase.cs.ucla.edu/pub/javacc/ ,例如html,xml,python,vb…..,很多足够用了,呵呵。 javaCC 的使用 javaCC生成的文件中,最主要的是《Grammar》.java这个就是解析器的主程序了了,《Grammar》名由jj中定义。 现在根据例子说明jj文件的定义: BNF范式为: Expression ::= ( ( <NEWLINE> )* Simple_Expression <NEWLINE> )* <EOF> Simple_Expression ::= Term ( addop Term )* addop ::= <PLUS> | <MINUS> Term ::= Factor ( mulop Factor )* mulop ::= <TIMERS> | <OVER> Factor ::= <ID> | <NUM> | <MINUS> | <PLUS> | <LPAREN> Simple_Expression <RPAREN> /*这是一个整数的四则运算的例子*/ /* 运行 javaCC Grammar.jj javac *.java java Grammar >>> 1+1*(1+1) 3 >>>^Z */ PARSER_BEGIN(Grammar) /*解析代码的入口*/ public class Grammar { public static final int PlusOP=1; public static final int MinusOP=2; public static final int TimersOP=3; public static final int OverOP=4; public static void main(String args[]) throws ParseException { Grammar parser = new Grammar(System.in); parser.Expression(); } } PARSER_END(Grammar) SKIP : /* 不处理的字符*/ { " " | "/t" } TOKEN : /*生成token的字符定义*/ { < ID: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","0"-"9"] )* > | < NUM: ( ["0"-"9"] )+ > | < PLUS: "+" > | < MINUS: "-" > | < TIMERS: "*" > | < OVER: "/" > | < LPAREN: "(" > | < RPAREN: ")" > | <NEWLINE: ("/r/n"|"/n"|"/r")> } void Expression() : /*完成 Expression ::=( ( <NEWLINE> )* Simple_Expression <NEWLINE> )* <EOF> 的配陪*/ { int value=0; /* 这个{}中是Expression()的定义的局部变量*/ } { { System.out.print(">>>"); } ( (<NEWLINE> /* 首先匹配NEWLINE 这个taken,完成后转到下一个解析*/ { System.out.print(">>>"); /*在<NEWLINE>下的{}中为假如匹配到<NEWLINE>执行的java代码。*/ } )* value= Simple_Expression() <NEWLINE> /*在换行之前Simple_Expression()解析表达式 ,输入换行后,一个预算解析完成*/ {System.out.println(value); System.out.print(">>>");/*在<NEWLINE>下的{}中为完成表达式解析,匹配到<NEWLINE>执行的java代码。*/ } )* <EOF> /*系统定义的taken,输入结束符*/ } int Simple_Expression() : /*完成Simple_Expression ::=bnf Term ( addop Term )*配陪 */ { /* 这个{}中是Simple_Expression()的定义的局部变量*/ int value; int tValue; int op; } { value= Term (){} /*配陪Term 相*/ ( op=addop() tValue=Term() { switch(op) { case PlusOP: value=value+tValue; break; case MinusOP: value=value - tValue; break; } } )* /*匹配 ( addop Term )* */ { return value; } } int addop() : {} { <PLUS> { return PlusOP; } | <MINUS> { return MinusOP; } } int Term() : { int value; int tValue; int op; } { value=Factor(){} ( op=mulop() tValue=Factor() { switch(op) { case TimersOP: value=value * tValue; break; case OverOP: value=value / tValue; break; } } )* { return value; } } int mulop() :{} { <TIMERS> { return TimersOP; } | <OVER> { return OverOP; } } int Factor() : { int value; Token t; } { t=<ID> /*获得<ID>的解析的值*/ { value=100; return value; } | t=<NUM> { value= (Integer.valueOf(t.image)).intValue(); return value; } | t=<MINUS> { value=0-Factor(); return value; } | t=<PLUS> { value=Factor(); return value; } | <LPAREN> value=Simple_Expression() <RPAREN> { return value; } } 根据例子: 基本上是一个taken下跟一个{}用于处理当前tabkn的java代码 jjTree的使用: jjTree的使用,需要根据实际情况写自己的Node类,但是都必须实现Node.java接口,jjTree提供一个SimpleNode.java的简朴实现,也可以继续它,或者重写这个类。 给出一个javaCC自己带例子,也是四则运算: 语法定义: Start ::= Expression ";" Expression ::= AdditiveExpression AdditiveExpression ::= ( MultiplicativeExpression ( ( "+" | "-" ) MultiplicativeExpression )* ) MultiplicativeExpression ::= ( UnaryExpression ( ( "*" | "/" | "%" ) UnaryExpression )* ) UnaryExpression ::= "(" Expression ")" | Identifier | Integer Identifier ::= <IDENTIFIER> Integer ::= <INTEGER_LITERAL> options { MULTI=true; VISITOR=true; /*实现匹配的visitor模式代码*/ NODE_DEFAULT_VOID=true; /* 解析函数默认不生成node类*/ } /*jtt 默认的生成node类名,都带AST前缀加上当前解析的语意的名称*/ PARSER_BEGIN(eg4) class eg4 { public static void main(String args[]) { System.out.println("Reading from standard input..."); eg4 t = new eg4(System.in); try { ASTStart n = t.Start(); eg4Visitor v = new eg4DumpVisitor(); n.jjtAccept(v, null); System.out.println("Thank you."); } catch (Exception e) { System.out.println("Oops."); System.out.println(e.getMessage()); e.printStackTrace(); } } } PARSER_END(eg4) SKIP : { " " | "/t" | "/n" | "/r" | <"//" (~["/n","/r"])* ("/n"|"/r"|"/r/n")> | <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> } TOKEN : /* LITERALS */ { < INTEGER_LITERAL: <DECIMAL_LITERAL> (["l","L"])? | <HEX_LITERAL> (["l","L"])? | <OCTAL_LITERAL> (["l","L"])? > | < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > | < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > | < #OCTAL_LITERAL: "0" (["0"-"7"])* > } TOKEN : /* IDENTIFIERS */ { < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* > | < #LETTER: ["_","a"-"z","A"-"Z"] > | < #DIGIT: ["0"-"9"] > } ASTStart Start() #Start : {} /* #Start生成定义的节点类,名称为 前缀 + Start.Java*/ { Expression() ";" { return jjtThis; } } void Expression() : {} { AdditiveExpression() } void AdditiveExpression() : {} { ( MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )* ) #Add(>1) /* Add # 当满意条件(>1),Add生成定义的节点类,名称为 前缀 + Add.Java*/ } void MultiplicativeExpression() : {} { ( UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )* ) #Mult(>1) /* # Mult 当满意条件(>1),Mult生成定义的节点类,名称为 前缀 + Mult.Java*/ } void UnaryExpression() : {} { "(" Expression() ")" | Identifier() | Integer() } void Identifier() #MyOtherID : /* # MyOtherID生成定义的节点类,名称为 前缀 + MyOtherID.Java*/ { Token t; } { t=<IDENTIFIER> { jjtThis.setName(t.image); } } void Integer() #Integer : {} /* # Integer生成定义的节点类,名称为 前缀 + Integer.Java*/ { <INTEGER_LITERAL> } jjDoc的使用很简朴 。 假如需要生成其它语言的(例如C#)解析器,除了处理C的yacc和lex外,ANTLR(http://www.antlr.org/)也是一个不错的选择。 返回类别: 教程 上一教程: Java是传值还是传引用 下一教程: Tomcat配置心得及相关资料 您可以阅读与"javaCC学习笔记"相关的教程: · java 学习笔记 · 学习笔记之 EQUALS() VS. == 和STRING对象的2种创建过程 · 《Effective Java》学习笔记(1) · 《Effective Java》学习笔记(2) · 今天总算看完了log4j,心情不错!把自己的学习笔记拿出来给大家共享一把 |
![]() ![]() |
快精灵印艺坊 版权所有 |
首页![]() ![]() ![]() ![]() ![]() ![]() ![]() |