2012-03-13 55 views
3

我正在嘗試爲由作業組成的非常簡單的語言生成LALR語法。例如:LALR語法,尾隨逗號和多行列表分配

foo = "bar" 
bar = 42 

語言也應該處理值的列表,例如:

foo = 1, 2, 3 

但我也想處理多條線路列表:

foo = 1, 2 
     3, 4 

尾隨逗號(對於單身人士和語言靈活性):

foo = 1, 
foo = 1, 2, 

很顯然,無論是在同一時間:

foo = 1, 
     2, 
     3, 

我能寫尾隨逗號或多行列表中的語法,而不是都在同一時間。

我的語法是這樣的:

content : content '\n' 
     : content assignment 
     | <empty> 

assignment : NAME '=' value 
      | NAME '=' list 

value : TEXT 
     | NUMBER 

list : ??? 

注:我需要在語法中的 '\ n' 禁止這種代碼:

foo 
= 
"bar" 

由於通過提前

安託萬。

+0

你*可以*看看JavaScript,Go和Scala(可能更多,這些都離開我的頭頂)如何推斷分號。但要警告的是,這會導致陷入困境(表達式延伸到換行符),並且不少程序員會討厭它。也許你應該添加更多的限制(比如「parens/brakets/braces中的只有表達式可以擴展到多行)」,這就是Python所做的)。 – delnan 2012-03-13 22:23:59

+0

其實,我的語言不是一種編程語言,而是一種配置格式,所以沒有表達。我考慮在列表中添加一些內容,但是如果可以的話,我更喜歡。 – Antoine 2012-03-13 22:35:07

+0

你能提供一個鏈接到你的解析代碼,以便我們可以玩你的語法,看看它的工作原理和不是什麼? – 2012-03-14 08:30:28

回答

2

它看起來像你的配置語言基本上是自由形式。我會忘記在語法中使用換行符作爲標記。如果你想要換行符限制,你可以將它作爲一些詞法綁定規則,解析器調用一個添加到詞法分析器的小API來通知詞法分析器它在語法中的位置,詞法分析器可以決定是否接受換行符或拒絕它們的錯誤。

試試這個語法。

%token NAME NUMBER TEXT 

%% 

config_file : assignments 
      | /* empty */ 
      ; 

assignments : assignment 
      | assignments assignment 
      ; 

assignment : NAME '=' values comma_opt 

comma_opt : ',' | /* empty */; 

values : value 
     | values ',' value 
     ; 

value : NUMBER | TEXT ; 

它爲我構建沒有衝突。我沒有運行它,但一個y.output的休閒閱讀看起來像過渡是理智的。

此語法,當然,允許

foo = 1, 2, 3, bar = 4, 5, 6 xyzzy = 7 answer = 42 

而不與詞法分析器的附加通信。

您的限制意味着換行符只允許在值中使用。兩個名稱標記絕不能出現在同一行上,並且=必須與前面的NAME出現在同一行(可能還必須有第一個值)。

基本上,當解析器掃描第一個值時,它可以告訴詞法分析器「現在正在掃描值,打開接受換行符」。然後當comma_opt減少時,可以再次關閉。當comma_opt減少時,詞法分析器可能已經讀取了下一個分配的NAME標記,但它可以檢查這發生在與以前的NAME不同的行上。你會希望你的詞法分析器能夠跟蹤準確的行數。

+0

我測試了你的想法,可能不完全如你所述,但它的工作原理:-)。謝謝!爲了記錄,我添加了一個檢查,如果解析器中記錄的「當前行」與詞法分析器中的當前行相同,並在其他情況下設置「當前行」,則會引發異常。此檢查在每個分配或分區規則中調用。 – Antoine 2012-03-15 19:58:55

0

我對此沒有太多的經驗,但會這樣做嗎?

listvalue : value , 
      | value '\n' 
      | value , '\n' 

list : listvalue list