為什么要研究這些,除了個人興趣之外,還有可以了解語言是怎樣解析字符串生成邏輯代碼。
他的應用性也是非常之廣,如人工智能方面,把復雜的邏輯抽象成簡單的文法,不懂編程的人都可以使用
說到人工智能,數據庫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 特性我認為就兩大,1是JSON 2.是回調。我個人是非常喜歡JSON的