[英]Parsing a “simple” grammar
提前抱歉; 我相信這個問題對於那些習慣使用解析器和語法的人來說幾乎是愚蠢的,但這些對我來說都是外國話題,這是我試圖輕輕地踩到需要它們的實際案例。
我想為下面的“語言”編寫一個解析器,它包含一個看起來像這樣的“特殊結構”:
\command[ options ]{ contents }
內容可以是任何內容,包括嵌套命令,並且可以包含轉義括號或反斜杠\\{ \\} \\\\
。 我意識到“任何事情”並不具體,但理想情況下,如果可能的話,應該通過匹配括號(不包括轉義的括號)來確定它們。
選項應該是逗號分隔的賦值表達式如列表name = value
,但該值也可以是含有一個引用字符串=
或,
字符。 最后,以前的name
和command
應該驗證正則表達式\\w[\\w\\d\\._-+*]*
- 也就是說,第一個字符應該是一個字母,剩下的字符應該是字母,數字或其中一個. _ - + *
. _ - + *
。
用正則表達式寫這個似乎過於復雜(例如,因為值可能包含帶引號的字符, =
,否則將分配賦值或名稱/值對)。 所以我認為這里最合適的工具是語法,但是盡管表面讀數很多,但我不確定如何編寫它(BNF,PEG等?),使用哪種類型的解析器(LR,遞歸正確等等?) ,以及如何在實際程序中使用解析輸出。
我更喜歡Python的答案,它解釋了標簽,但當然如果必要/更適合我會非常滿意的工具組合。
注意:這不是關於LaTeX。 我認識到當然是相似的,但是LaTeX比以前的語言復雜得多,例如字符代碼根據上下文而變化。 我只是要求一個實際的例子(我認為)對於SO來說很簡單,但在我的日常工作中對我來說已經很有用了。
首先用正式表達你的語法,用你喜歡的任何表示法。 例如,根據您的描述,EBNF將是這樣的:
program := element+
element := command | literal
literal := (not '\')+
command := '\'identifier options? '{' program '}'
options := option | options ',' option
option := identifier '=' value
value := number | string
string := '"' (escape | not '\' or '"')* '"'
escape : = '\' char
然后將其提供給解析器生成器(pyParsing,pyYACC,ANTLR)或手動編寫解析器。 在后一種情況下,自上而下是最簡單的選項:從語法頂部開始,將每個規則轉換為一個函數,該函數將返回一個解析的AST節點並使用輸入或返回任何內容或拋出。 例:
def program():
elements = []
while next_sym():
elements.append(element())
return {'type': 'program', 'children': elements}
def element():
return command() or literal()
def command():
if next_sym() == '\\':
get_sym()
...parse command here
return {'type': 'command', 'children': ...}
return None
其中next_sym
返回輸入中的下一個符號(或EOF上的None
), get_sym
該符號並前進輸入緩沖區。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.