2016-05-31 35 views
1

我有一個Jison一段代碼,看起來像這樣:如何在Jison中檢測新行?

%lex 
%options flex 

%{ 
if (!('regions' in yy)) { 
    yy.regions = []; 
} 
%} 

text    [a-zA-Z][a-zA-Z0-9]* 

%% 

\s+     /* skip whitespace */ 
\n+     return 'NL'; 
","     return ','; 
"-"     return '-'; 
"["     return '['; 
"]"     return ']'; 
{text}    return 'TEXT'; 
<<EOF>>    return 'EOF'; 

/lex 

%start expressions 

%% 

expressions 
    : content EOF 
     { 
      console.log(yy.regions); 
      return yy.regions; 
     } 
    | EOF 
     { 
      console.log("empty file"); 
      return yy.regions; 
     } 
    ; 

content 
    : line NL content 
     { console.log("NL"); } 
    | line content 
     { console.log("no NL"); } 
    //| line NL 
    // { console.log("parsing line with NL"); } 
    | line 
     { console.log("parsing line"); } 
    ; 

line 
    : '[' text ']' 
     { yy.regions.push($2); $$ = $2; } 
    ; 

text 
    : TEXT 
     { $$ = $1; } 
    ; 

這是我的輸入看起來像此刻(我從我計劃有,我想建立最基本的結構開始它從那裏):

[sectionA] 
[sectionB] 
[sectionC] 

我遇到的問題是,沒有檢測到新行。它總是進入line content,永遠不會進入line NL content。後來我想分析的東西,看起來更像是這樣的:

[sectionA] 
something1, something2, something3 
something4, something5, something6 

[sectionB] 
something4, something5, something6 

[sectionC] 
something4, something5, something6 
something4, something5, something6 
something4, something5, something6 

在未來,這會變得有點複雜,但我最初的想法是一種打破它每行的基礎上(新行在許多情況下將作爲分隔符)。我對這個東西完全陌生,所以我可能對如何解決這個問題有一個完全錯誤的想法。所以我的問題是如何檢測新的線?此外,如果有更好的方法來處理我想要做的事,任何建議都是值得歡迎的。謝謝。

回答

4

這兩個規則將與後面:

\s+     /* skip whitespace */ 
\n+     return 'NL'; 

由於第一個是第一次,它會獲勝。 (Flex會給你一個關於第二條規則未被使用的警告,但我不認爲jison會做這種分析。)

但是,更改規則的順序不會有幫助,因爲第一條規則將匹配SPACENL,從而吞噬換行符,如果它前面有空格。您需要更改空白規則以僅匹配不是換行符的空白。

一種可能性是:

\n\s*  return 'NL'; 
[^\S\n]+ /* ignore whitespace other than newlines */ 

第一圖案將與後面跟着由空格的任何序列,這意味着它將匹配多個換行。當輸入中有空行時,這將避免返回多個NL標記;除非空行顯着,否則這可能是你想要的。

第二種模式避免匹配任何換行符,所以它不能與第一個模式衝突。

有人擔心使用Windows行結尾(\r\n),但由於Javascript的\s包括\r,這裏沒有真正的問題。 \r將被第二個規則忽略,\n將被第一個規則識別。如果您認爲有必要,您可以將第一條規則更改爲\r?\n\s*以提高效率,但可能不會更快。

+0

它工作。非常感謝。它完全符合我的需求,而且答案通常很豐富。 – pootzko

0

@ rici的回答很有幫助,它讓我走上了正軌。然而,[ \t]+沒有做我所需要的。這是兩個行我最終使用:

(\r?\n)+\s*   return 'NEWLINE'; 
[^\S\r\n]+   ; /* whitespace */ 

我發現他們here

編輯:@ rici的更新答案比這個答案更清晰,並且正是我所需要的,所以我接受了。

+0

這與將空白字符列表添加爲'\ r'完全相同,除了一個重要的區別:您的原始字符將爲任何數量的換行符返回一個NEWLINE標記(實際上會忽略空白行),而此答案中的一個爲每個換行符發送一個NEWLINE標記。再想一想,如果你想忽略空白行的話,我推薦的是'\ n \ s *'。 – rici

+0

@rici - 我不確定我是否理解你剛剛寫的內容。你是說如果我使用\ n \ s *而不是\ n +,那會忽略多個連續的空白行?基本上我只想知道什麼時候出現空行,所以我可以使用它作爲分隔符,然後自行解析下一行。如果這是有道理的。如果你有比這個答案更好的解決方案,我會很樂意接受它,如果它符合我剛剛描述的內容。 – pootzko

+0

一般來說,我覺得在尋找有關這些規則的適當文檔方面有點失落,因爲每種語言都有自己的怪癖,關於如何進行這種正則表達式匹配,並且似乎沒有足夠清晰的信息來說明如何在Jison /野牛。 – pootzko