2012-09-24 80 views
2

我想爲允許轉義標記分隔符的標記語言創建Jison(Bison)語法。轉義字符語法

這將是有效的:

I like apples 
I like [apples, oranges, pears] 
I like [apples, oranges, pears] and [peanut butter, jelly] 
I like [apples, oranges, pears] \[when they're in season\] 
I like emoticons :-\] 

的例子或許會作爲被解釋如下(以JSON表示):

["I like apples"] 
["I like ", ["apples", "oranges", "pears"]] 
["I like ", ["apples", "oranges", "pears"], " and ", ["peanut butter", "jelly"]] 
["I like ", ["apples", "oranges", "pears"], " [when they're in season]"] 
["I like emoticons :-]"] 

脫逃[]\,是最小的,但它可能是有道理的允許任何可打印的字符被轉義,即使不需要轉義也是如此。

如果轉義不可打印的字符不被支持,那會很好。也就是說,一行末尾的\將是非法的。這可能免費與正則表達式.,因爲它可能不包含換行符,但它也應該發生其他不可打印的字符。

是很困難的谷歌這一點,因爲它混合了很多成果在野牛定義逃逸文字字符等

什麼是支持的自定義野牛轉義字符最優雅的方式語言?

編輯

這裏是我到目前爲止and can be tested on Jison,但它不工作(只是返回1如果有的話),我不認爲該文本將到達轉義 - 這將需要第二通過。這是可以避免的嗎?

/* description: markup */ 

/* lexical grammar */ 
%lex 
%% 

(\\.|[^\\\[])+   return 'TOPTEXT' 
(\\.|[^\\\[\]\,])+  return 'TEXT' 
\-?[0-9]+("."[0-9]+)?\b return 'NUMBER' 
".."|"-"     return '..' 
"["      return '[' 
"]"      return ']' 
","      return ',' 
<<EOF>>     return 'EOF' 

/lex 

%start markup 

%% 

markup 
    : template EOF 
     { return $template; } 
    ; 

template 
    : template TOPTEXT 
     { $$ = $template.push($TOPTEXT); } 
    | template dynamic 
     { $$ = $template.push($dynamic); } 
    | /* empty */ 
     { $$ = []; } 
    ; 

dynamic 
    : '[' phraselist ']' 
     { $$ = $phraselist; } 
    ; 

phraselist 
    : phraselist ',' phrase 
     { $$ = $phraselist.push($phrase); } 
    | /* empty */ 
     { $$ = []; } 
    ; 

phrase 
    : TEXT 
     { $$ = $phrase.push($TEXT); } 
    | phrase dynamic 
     { $$ = $phrase.push($dynamic); } 
    | /* empty */ 
     { $$ = []; } 
    ; 

回答

2

我認爲你的代碼有多個問題。

第一個(這也解釋了1輸出)是[].push返回列表的新長度,所以你想要什麼可能是推,並然後定義值:

template 
: template TOPTEXT 
    { $template.push($TOPTEXT); $$ = $template; } 
| template dynamic 
    { $template.push($dynamic); $$ = $template; } 
| /* empty */ 
    { $$ = []; } 
; 

其他事情是,你似乎試圖讓太多的東西同時工作,而沒有確定你想要他們,或者他們實際上是按照他們應有的方式工作。

也許一個更好的策略應該是讓你從小處着手,使它在當時從基礎開始工作。

例如,你可以首先確保您有詞法分析器對每一種情況下工作,用一個簡單的語法,只是打印出的標記測試:

%lex 
%% 

(\\\\|\\\[|\\\]|\\\,|[^,\\\[\]])+ return 'TEXT' 
\-?[0-9]+("."[0-9]+)?\b    return 'NUMBER' 
".."|"-"       return 'RANGE' 
"["         return '[' 
"]"         return ']' 
","         return ',' 

/lex 

%start lexertest 

%% 

lexertest: 
token lexertest 
| /* empty */ 
; 

token: 
TEXT { console.log("Token TEXT: |" + $TEXT + "|"); } 
| 
NUMBER { console.log("Token NUMBER: |" + $NUMBER + "|"); } 
| 
'['  { console.log("Token ["); } 
| 
']'  { console.log("Token ]"); } 
| 
','  { console.log("Token ,"); } 
| 
'RANGE' { console.log("Token RANGE: |" + $1 + "|"); } 
; 

注:當運行瀏覽器,console.log輸出將只在開發人員工具中使用。您可能會發現在命令行中使用Jison並使用script like this (for Bash)可以更容易使用多個輸入進行測試。

然後你細化它,直到你滿意爲止。 當您對詞法分析器滿意後,您就開始使語法工作,並再次測試一條規則。每當你想調試詞法分析器的輸出時,保持上面的規則,你可以改變%start規則。

最後,你可能會發現,你從不需要EOF首先,也許你不會需要兩個不同的規則來匹配自由文本,畢竟。

希望它有幫助。

+0

大推()!很好的建議,謝謝。但是我的期望是什麼應該避開那些逃脫的角色?它可以由詞法分析器來完成,還是需要一種逐字符處理字符的語法?或者是什麼? –

+1

@uosɐs是的,我認爲這是詞法分析器處理轉義的工作。如果我明白你的意思,就是說,從token值中去掉反斜槓,你可能會得到類似'{yytext = yytext.replace(/\\(()),g''$ 1')的東西。返回'TEXT'; } - 字符串替換應用於令牌值。 – elias

+0

這是一個很好的建議,我想我會一起去。我還發現這些鏈接提供了一種無需正則表達式即可實現它的方式。 http://zaach.github.com/jison/docs/#lexical-analysis http://dinosaur.compilertools.net/flex/flex_11.html http://flex.sourceforge.net/manual/How-do-I -expand-backslash_002descape-sequences-in-C_002dstyle-quoted-strings_003f.html –