1. 程式人生 > >工程中的編譯原理 -- Mapfile解析器

工程中的編譯原理 -- Mapfile解析器

前言

Mapfile是MapServer用來描述一個地圖的配置檔案。它是一個很簡單的宣告式語言,一個地圖(Map)可以有多個層(Layer),每個層可以有很多屬性(鍵值對)。在一個層的定義中,還可以定義若干個類(Class),這個類用以管理不同的樣式(Style)。而每個類或者樣式都可以由若干個屬性(鍵值對)。

這裡有一個實際的例子:

Ruby
123456789101112131415 LAYERNAME"counties"DATA"counties-in-shaanxi-3857"STATUSdefaultTYPEPOLYGONTRANSPARENCY70CLASSNAME"polygon"STYLECOLOR255255255OUTLINECOLOR404452ENDENDEND

最簡單的層的定義

最簡單的情形是,我們定義了一個層Layer,但是沒有指定任何的屬性:

Shell
12 LAYEREND

我們期望parser可以輸出:

Shell
1 {layer:null}

要做到這一步,首先需要定義符號LAYER和END,以及一些對空格,非法字元的處理等:

Shell
123456 \s+/*skip whitespace*/\n|\r\n/*skip whitespace*/"LAYER"return"LAYER""END"return"END"<<EOF>>return'EOF'.return'INVALID'

對於,空格,回車換行等,我們都直接跳過。對應的BNF也非常簡單:

Shell
1234567 expressions:declsEOF{return$1;};decls:LAYEREND{$$={layer:null}};

為層新增屬性

接下來我們來為層新增Name屬性,首先還是新增符號NAME和對字串的定義。這裡的字串被定義為:由雙引號括起來的所有內容。

Shell
123 "NAME"return"NAME"'"'("\\"["]|[^"])*'"'   return 'STRING'[a-zA-Z]+return'WORD'

然後我們就可以為BNF新增一個新的節:

Shell
12345678 decls:LAYERdeclEND{$$={layer:$2}};decl:NAMESTRING{$$=$2.substring(1,$2.length-1)};

在decl中,我們將獲得的字串兩頭的引號去掉$2.substring。這樣decl的值就會是字串本身,而不是帶著雙引號的字串了。修改之後的程式碼可以解析諸如這樣的宣告:

Shell
123 LAYERNAME"counties"END

併產生這樣的輸出:

Shell
1 {layer:'counties'}

但是如果我們用來解析兩個以上的屬性:

Shell
1234 LAYERNAME"counties"DATA"counties-in-shaanxi-3857"END

解析器會報告一個錯誤:

Shell
12345678910111213141516171819 $node map.jsexpr/Users/jtqiu/develop/ideas/jison-demo/mapfile/map.js:106thrownewError(str);^Error:Parse error on line2:..."counties"DATA"counti----------------------^Expecting'END',got'WORD'atObject.parseError(/Users/jtqiu/develop/ideas/jison-demo/mapfile/map.js:106:15)atObject.parse(/Users/jtqiu/develop/ideas/jison-demo/mapfile/map.js:171:22)atObject.commonjsMain[asmain](/Users/jtqiu/develop/ideas/jison-demo/mapfile/map.js:620:27)atObject.<anonymous>(/Users/jtqiu/develop/ideas/jison-demo/mapfile/map.js:623:11)atModule._compile(module.js:456:26)atObject.Module._extensions..js(module.js:474:10)atModule.load(module.js:356:32)atFunction.Module._load(module.js:312:12)atFunction.Module.runMain(module.js:497:10)atstartup(node.js:119:16)

即,期望一個END符號,但是卻看到了一個WORD符號。我們只需要稍事修改,就可以讓當前的語法支援多個屬性的定義:

Shell
123456789101112131415161718 decls:LAYERpairsEND{$$={layer:$2}};pairs:pair{$$=$1}|pairspair{$$=merge($1,$2)};pair:NAMESTRING{$$={name:$2.substring(1,$2.length-1)}}|DATASTRING{$$={data:$2.substring(1,$2.length-1)}};

先看,pair的定義,它由NAME STRING或者DATA STRING組成,是我們語法中的終結符。再來看pairs的定義:

Shell
1 pairs:pair|pairs pair;

這個遞迴的定義可以保證我們可以寫一條pair或者多條pairs pair屬性定義語句。而對於多條的情況,我們需要將這行屬性規約在一起,即當遇到這樣的情形時:

Shell
12 NAME"counties"DATA"counties-in-shaanxi-3857"

我們需要產生這樣的輸出:{name: “counties”, data: “counties-in-shaanxi-3857”}。但是由於符號是逐個匹配的,我們會得到這樣的匹配結果:{name: “counties”}和{data: “counties-in-shaanxi-3857”},因此我們需要編寫一個簡單的函式來合併這些屬性:

Shell
123456789101112 functionmerge(o1,o2){varobj={};for(varkino1){obj[k]=o1[k];}for(varvino2){obj[v]=o2[v];}returnobj;}

按照慣例,這種自定義的函式需要被定義在%{和}%括起來的section中:

Shell
12345678910111213141516171819202122232425262728293031

相關推薦

工程編譯原理 -- Mapfile解析

前言 Mapfile是MapServer用來描述一個地圖的配置檔案。它是一個很簡單的宣告式語言,一個地圖(Map)可以有多個層(Layer),每個層可以有很多屬性(鍵值對)。在一個層的定義中,還可以定義若干個類(Class),這個類用以管理不同的樣式(Style)。

JDKJAXP尋找XML解析的順序

工作中,使用JAVA的JAXP讀取解析XML檔案中,就碰到了一件奇件的事。在Web工程中,除錯發現JAXP實際使用的是Xerces解析器,可是,當將工程中的一個小Swing工具,與Web使用一樣的jar包,打成一個可執行的jar包時,除錯卻發現JAXP實際使用的是Crimso

工程編譯原理 -- Jison入門篇

前言 在程式碼編寫中,很多時候我們都會處理字串:發現字串中的某些規律,然後將想要的部分抽取出來。對於發雜一些的場景,我們會使用正則表示式來幫忙,正則表示式強大而靈活,主流的變成語言如Java,Ruby的標準庫中都對其由很好的支援。 但是有時候,當接收到的字串結構更加

javascript解析原理

nbsp .html html www div set alert define style   瀏覽器在讀取HTML文件的時候,只有當遇到<script>標簽的時候,才會喚醒所謂的“JavaScript解析器”開始工作。 JavaScript解析器工作步驟 1

工作的那些坑(2)——語法解析

波蘭表達式 png 其中 新增 commons 表達式 http cal fine 工作項目裏用到線性回歸算法,用於計算賬戶的分值,表明某賬戶是否是有風險的賬戶。其中參數都配好了,代碼裏直接用逆波蘭表達式解析即可。本來事情到這裏已經結束,突然來了新的需求:賬戶算出來的分數較

編譯生成C++導出函數dll,並在C#工程測試

lec ces 說明 cnblogs c# point article span targe 編譯生成過程: 1.建立dll工程 選擇新建visual C++的 這兩個類型工程,都會出現下面界面,在這裏設置生成dll: 2.設置項目: 項目屬性中設置: 3.相

js解析的執行原理

html 變化 ron 使用 meta utf 新的 class 而且 首先看一段代碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8" />

LAMP原理架構解析(三):LAMP編譯安裝

mariadbCentos7.3編譯安裝LAMP目錄:編譯環境LAMP編譯安裝一.環境準備 征信數據庫數據事件不一致導致數據(RAC集群)混亂,PLSQL查詢時間和數據庫時間不一致,嚴重影響業務本文出自 “每天進步一點點,自律” 博客,請務必保留此出處http://wbxue.blog.51cto.

Question20180104 對比編譯器、解釋與Javac編譯原理

即時編譯 inf ali pro 友好 pre 目標 缺點 java、 編譯器與Javac編譯原理   在前文我們知道了Java是一種編譯語言和解釋語言,它的源代碼經過編譯器Javac編譯為能夠被JVM識別的二進制語言,然後JVM將其解釋為能夠被平臺識別的機器語言。那麽什

SpringMVC用於綁定請求數據的註解以及配置視圖解析

SpringMVC 視圖解析器 @RequestHeader 綁定集合參數 @CookieValue SpringMVC中用於綁定請求數據的註解 在上一篇文章中我們簡單介紹了@RequestMapping與@RequestParam註解,知道了如何去配置地址映射,本篇則介紹一些用於處理re

SSM-SpringMVC-10:SpringMVCPropertiesMethodNameResolver屬性方法名稱解析

port public 方法名 return ati AC schema 定義 try ------------吾亦無他,唯手熟爾,謙卑若愚,好學若饑------------- 上次的以繼承MultiActionController可以實現一個處理器中多個處理方

SSM-SpringMVC-11:SpringMVCParameterMethodNameResolver參數方法名稱解析

地址 string val 1.0 步驟 端口號 pro let enc ------------吾亦無他,唯手熟爾,謙卑若愚,好學若饑------------- 或許曾經的我們也見過一種方式http://localhost:8080/項目名/後臺servlet

Redhat6.5搭建DNS分離解析服務

DNS 分離解析 分離解析的域名服務器實際也是主域名服務器,這裏所說的分離解析主要是指根據不同的客戶端提供不同的域名解析記錄。來自不同地址的客戶機請求解析同一域名時,為其提供不同的解析結果。下面將以如下拓撲完成分離解析實驗模擬:實驗要求:在某公司內部有一臺提供web服務的服務器IP為192.168.1

net 編譯報錯:編輯或項目正在嘗試簽出在內存修改的文件,這將導致保存該文件

是否 嘗試 過程 執行 中修改 輸出 只讀 內存 去掉只讀屬性 1,報錯提示: 編輯器或項目正在嘗試簽出在內存中修改的文件,這將導致保存該文件。 在生成過程中保存文件是危險的,這可能會在將來導致不正確的生成輸出。 是否仍然繼續簽出? 2,原因:licenses.licx屬性

vue數據雙向綁定原理-解析Complie

ava div des for lse 遍歷 `` dde move ?? 1)vue數據雙向綁定原理-observer ?2)vue數據雙向綁定原理-wather? 3)vue數據雙向綁定原理-解析器Complie vue數據雙向綁定原理, 和簡單的實現,本文將實現mv

URLParser:很實用的URL引數解析(JAVA程式碼方便獲取QueryString的get引數)

很實用的URL引數解析器(JAVA程式碼中方便獲取QueryString中的get引數) package com.kaishustory.quick.commons.text; import java.io.UnsupportedEncodingException; import

Spring原始碼解析(十六)——AOP原理——獲取攔截鏈——MethodInterceptor

   *     3)、目標方法執行    ;  *         容器中儲存了元件的代理物件(cglib增強後的物件),這個物件裡面儲存了詳細

編譯原理LR(0)專案集規範族的構造

編譯原理中LR(0)專案集規範族的構造   此文略長。我也沒想到這寫起來這麼多,但對構造過程絕對清楚,一步步慢慢看吧。      LR的第一個L和LL的第一個L含義相同,即從左到右掃描句子 ,第二個R表示Right most最右推導。      在通常的描述中,後面還有一個括號裡面的數字如,L

Sass的巢狀---結合線上編譯詳解選擇巢狀、屬性巢狀、偽類巢狀

推薦部落格:https://blog.hypers.io/2017/08/06/sass%20&%20compass%20%E6%95%99%E7%A8%8B%20--%20%E8%AF%AD%E6%B3%95%E7%AF%87(%E4%B8%80)/?utm_source=tuicool&

eclipse增加工程檔案在windows資源管理開啟

方法有二: 一: 1.點選configurations,不同版本可能不一樣,大概就在這裡啦 2. 按截圖填寫即可,最後點選run,就開啟當前檔案所在的目錄啦 第二種方法: 安裝pathtools外掛, 外掛在http://code.google.com/p/path