javacc學習


為什么要研究這些,除了個人興趣之外,還有可以了解語言是怎樣解析字符串生成邏輯代碼。

他的應用性也是非常之廣,如人工智能方面,把復雜的邏輯抽象成簡單的文法,不懂編程的人都可以使用

說到人工智能,數據庫SQL查詢也算是,大家可能會覺得,這也算人工智能?

是的,如果程序員完全用過程方式去寫邏輯查詢的話,會瘋掉,像淘寶級別的數據,假設每天產生一個數據庫

如何多天查詢?群集數據庫如何分布式統計?

還有大型游戲的AI,一個怪物攻擊過程有:檢查狀態->掃描目標->選擇技能->計算傷害->保存數據->next ai

如果寫一個怪物還好點,但一個游戲不會只有一個怪物吧,成千上萬怎么辦?

 

我在這里保證,大家都能學會。哈哈

先來介紹下 bnf 文法,內容我就不復雜了

 

一些概念簡單說下

1.詞法元素

2.詞法標識

 

一組元素里包含多個標識,請看具體寫法

TOKEN:{

<PLUS:"+">

|<NUMBER:(["0"-"9"])+>

|<NUM: <NUMBER> | (<NUMBER>.<NUMBER> )* >

}

翻譯

詞法元素:{

<詞法標識1:"+">

|<詞法標識2:(["0"-"9"])+>

|<詞法標識3:<詞法標識2>+>

}

多個標識用 | 關聯起來,標識也可以嵌套也一標識

標識對應匹配的詞,可以用正則書寫.總的過講比正則簡單多了,但前提是你會正則

 

解析過程原理:

1.先定義各種詞法元素 可按操作符,變量關鍵詞,邏輯關鍵詞等草划分詞法元素

2.所謂的語法表達式 是結構節點編程 如果你精通結構編程,這點難不到你

 如元素與元素相似的就用兄弟節點,上下屬關系相似性不大就用父子節點

3.提取出來詞法標識 相應的值,做邏輯處理。這時候提取出來了,想干嘛就干嘛

下面來自牛人總結一幅圖

  

Javacc 簡介

JavaCC是一個詞法分析器和語法分析器的生成器。

這里列出我收集的資料

//基礎

//http://forfuture1978.iteye.com/blog/661678

//http://cs.lmu.edu/~ray/notes/javacc/

 

//sql

//http://www.codeproject.com/Articles/35748/An-Introduction-to-JavaCC

//http://www.codeproject.com/Articles/50377/Create-Your-Own-Programming-Language

 

//base

//http://ramkulkarni.com/blog/handling-some-of-the-warnings-and-errors-generated-by-javacc/

 

Jdk 默認是沒有的,要下載安裝

執行命令

java -cp E:\javacc-6.0\bin\lib\javacc.jar javacc exp.jj

 

Javacc 語法簡介

他可以跟 bnf 混編寫如 

 

 

int expr()  :{

int reslt = 0;

int i = 0;

Token t=null;

}

{

 

t =  <NUM>

{

  result =Integer.parseInt(t.image)

return result;

}

}

 

翻譯 混編

int expr()  :{ java 局部變量,聲明在這里 可以直接訪問 bnf  }

{

 

t =  <NUM> // 將 匹配的單詞賦值給 t

{

//{} JAVA代碼必須寫在 {}里

//javacc Token 對象有個重要屬性 image 是匹配出來的值

  result =Integer.parseInt(t.image)

return result;

}

}

 

 

一個完整的+-/*運算例子

分析:

邏輯優先級是 () 號,然后是 */ ,再到+-

 

 

options 

{ 

  static = false; 

}

PARSER_BEGIN(Calculator) 

package com.jj;

import java.io.PrintStream ; 

  public class Calculator { 

    public static void main( String[] args ) throws ParseException, TokenMgrError, NumberFormatException { 

      Calculator parser = new Calculator( System.in ) ; 

      parser.start( System.out ) ; 

    } 

    double previousValue = 0.0 ; 

  } 

PARSER_END(Calculator)

 

SKIP : { " " } 

TOKEN : { < EOL: "\n" | "\r" | "\r\n" > } 

TOKEN : { < PLUS : "+" > } 

TOKEN : { < MINUS : "-" > } 

TOKEN : { < TIMES : "*" > } 

TOKEN : { < DIVIDE : "/" > } 

TOKEN : { < NUMBER : <DIGITS> | <DIGITS> "." <DIGITS> | <DIGITS> "." | "." <DIGITS>> } 

TOKEN : { < #DIGITS : (["0"-"9"])+ > } 

TOKEN : { < OPEN_PAR : "(" > } 

TOKEN : { < CLOSE_PAR : ")" > } 

TOKEN : { < PREVIOUS : "$" > }

 

void start(PrintStream printStream) throws NumberFormatException : 

{} 

{ 

  ( 

    previousValue = Expression() 

    { printStream.println( previousValue ) ; } 

  )* 

}

double Expression() throws NumberFormatException : 

{ 

  double i ; 

  double value ; 

} 

{ 

  value = Term() 

  ( 

    <PLUS> 

    i= Term() 

    { value += i ; } 

    | 

    <MINUS> 

    i= Term() 

    { value -= i ; } 

  )* 

  { return value ; } 

}

double Term() throws NumberFormatException : 

{ 

  double i ; 

  double value ; 

} 

{ 

  value = Primary() 

  ( 

    <TIMES> 

    i = Primary() 

    { value *= i ; } 

    | 

    <DIVIDE> 

    i = Primary() 

    { value /= i ; } 

  )* 

  { return value ; } 

}

double Primary() throws NumberFormatException : 

{ 

  Token t ; 

  double d ; 

} 

{ 

  t=<NUMBER> 

  { return Double.parseDouble( t.image ) ; } 

  | 

  <PREVIOUS> 

  { return previousValue ; } 

  | 

  <OPEN_PAR> d=Expression() <CLOSE_PAR> 

  { return d ; }

}

 

 

如果還覺得復雜,你可以跳過,我還是有信心保證你也會寫的

 

下面直接josql 分析

其中核心代碼

 

void _Query(Query q):

{ 

List cols = null;

List fromItems = null;

List joins = null;

Expression where = null;

List orderBys = null;

List groupOrderBys = null;

List groupBys = null;

Expression having = null;

Limit limit = null;

        Limit grpLimit = null;

        Expression from = null;

        Map execute = null;

        boolean distinct = false;

}

{

    <K_SELECT>  [ LOOKAHEAD(2) <K_DISTINCT> { q.setWantDistinctResults (true); } ]

    cols = SelectItemsList(q)

    from = From() 

    [ where = WhereClause() ]

    [ LOOKAHEAD(2) groupBys = GroupBys() ]

    [ having = Having() ]

    [ LOOKAHEAD(GroupOrderBys()) groupOrderBys = GroupOrderBys() ]

    [ orderBys = OrderBys() ]

    [ LOOKAHEAD(GroupLimit()) grpLimit = GroupLimit() ]

    [ limit = Limit() ]

    [ execute = ExecuteOn() ]

 

    { 

      // We set all the values since they are all dependent on the class 

      // being available.

      q.setFrom (from); 

      q.setColumns (cols);

      q.setWhere (where);

      q.setHaving (having);

      q.setGroupByOrderColumns (groupOrderBys);

      q.setOrderByColumns (orderBys);

      q.setGroupByColumns (groupBys);

      q.setGroupByLimit (grpLimit);

      q.setLimit (limit);

      q.setExecuteOnFunctions (execute);

    }

}

 

無非是提取出相應的參數,保存起來做處理而已,然提取過程可能會很復雜但基本是是結構節點編程

下面我來總結一下:

1.以sql 為例語法格式無非是 a指令 a參數 b指令 b參數 N... N個拼起來

2.提取出來的參數再做處理過程

 

我們來做個抽象演變

a指令 a參數 b指令 b參數 N...

直接拋開解析語法過程

Query( a參數,  b參數 , c參數,n...)

這種書寫也可以達到工人智能,但不太友好

 

再來一層抽象

{

a指令 : a參數,

b指令 : b參數,

n....

}

 

無錯,就是JSON

大多數人對JSON 的認識還停留在數據方面

我總結下JSON 幾大特精:

1.數據

2.類

3.結構

4.協議

5.文法 (從上面演變)

JS 特性我認為就兩大,1JSON 2.是回調。我個人是非常喜歡JSON


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM