2014-10-04 45 views
3

前言存取控制字符串(ACS)與PEG.js解析器/口譯

我正在創建 CCESS Ç ONTROL 小號特林(或小號 ystem)( ACS)帶有PEG.js的字符串解析器/解釋器。 ACS字符串通常用於公告板系統(BBS)上,以檢查對電路板特定區域的訪問權限。例如,請參閱Renegade's ACS documentation

例ACS字符串

下面是一些簡單的字符串,他們的英語翻譯說明:

// Has GM123 OR NOT GM456 
GM123|!GM456 

// Has GM123 OR NOT (GM456 AND GM789) (note: AND is implied in this grammar if not specified) 
GM123|!(GM456GM789) 

// Has GM123 AND NOT GM456 OR has GM789 
GM123!GM456|GM789 

// Has GM1 OR (NOT GM2 OR GM3) 
GM1|(!GM2|GM3) 

我正在努力實現

我想什麼在這裏做的是解析解釋(或「運行」)ACS字符串,並最終結束最後的噓聲靠。

語法到目前爲止

下面是PEG.js語法我有一些了爲止。請注意,ACS字符串本身比上面的示例(我允許例如GM ['abc','def'])更復雜一點,但我認爲到目前爲止它是相當自我解釋的。

{ 
    function checkAccessSingle(acsName, arg) { 
    return true; 
    } 

    function checkAccessMulti(acsName, args, anyMatch) { 
    return true; 
    } 

    function makeNot(not, x) { 
    return not ? !x : x; 
    } 
} 

start 
    = acsString 


whitespaceChar 
    = ' ' 

ws 
    = whitespaceChar* 

lineTerminatorChar 
    = [\r\n\u2028\u2029] 

decimalDigit 
    = [0-9] 

integer 
    = decimalDigit+ { return parseInt(text(), 10); } 

asciiPrintableChar 
    = [ -~] 

singleAsciiStringChar 
    = !("'") asciiPrintableChar { return text(); } 

doubleAsciiStringChar 
    = !('"') asciiPrintableChar { return text(); } 

nonEmptyStringLiteral 
    = "'" chars:singleAsciiStringChar+ "'" { return chars.join(''); } 
/'"' chars:doubleAsciiStringChar+ '"' { return chars.join(''); } 

AND 
    = '&' 

OR 
    = '|' 

NOT 
    = '!' 

acsName 
    = n:([A-Z][A-Z]) { return n.join(''); } 

acsArg 
    = nonEmptyStringLiteral 
/integer 

acsArgs 
    = first:acsArg rest:(ws ',' ws a:acsArg { return a; })* { 
     var args = [ first ]; 
     for(var i = 0; i < rest.length; ++i) { 
     args.push(rest[i]); 
     } 
     return args; 
    } 

singleAcsCheck 
    = not:NOT? n:acsName a:acsArg* { 
    return function() { 
     makeNot(not, checkAccessSingle(n, a)); 
     } 
    } 
/not:NOT? n:acsName '[' a:acsArgs ']' { 
    return function() { 
     return makeNot(not, checkAccessMulti(n, a, false)); 
     } 
    } 
/not:NOT? n:acsName '{' a:acsArgs '}' { 
    return function() { 
     return makeNot(not, checkAccessMulti(n, a, true)); 
     } 
    } 

multiAcsCheck 
    = singleAcsCheck+ 

acsString = multiAcsCheck 

當我需要幫助

我有(如果沒有其他人我還沒有遇到呢!)的主要問題是處理優先用()和OR子句。這可能是簡單的,但我已經爲此工作了幾天,並且有一些短缺。再次,我最終試圖實現的是輸入一個ACS字符串並輸出最終的布爾結果。各種ACS「命令」(例如上面例子中的'GM')應該進行方法調用來完成骯髒的工作。

+0

不熟悉PEG.js,這聽起來像是一個問題,如果你在許多PEG.js社區中的一個站點上詢問它,可能會得到答案,在http://pegjs.majda.cz/development – 2014-10-12 20:39:29

+0

上列出。請查看此響應:http:/ /stackoverflow.com/questions/19790748/make-a-expression-for-string-string-string-on-peg-js它處理可變長度列表。 – orange 2014-10-25 21:12:00

+0

@BartKiers:我已經更新了示例以使用AND/OR。我不太清楚如何回答優先問題。我想從左到右評估,但是使用()優先分組。也許我沒有問正確的問題。 – NuSkooler 2014-11-04 19:52:37

回答

1

這裏有一個快速演示是正確分析你的榜樣輸入並顯示你怎麼能去的飛行評估表達式(這將返回一個布爾值):

{ 
    function check(name, value) { 
    // Dummy implementation: returns true when the name starts with 'A' 
    return name.charAt(0) == 'A'; 
    } 
} 

start 
= expr 

expr 
= or_expr 

or_expr 
= left:and_expr '|' right:expr { return left || right; } 
/and_expr 

and_expr 
= left:not_expr '&'? right:expr { return left && right; } 
/not_expr 

not_expr 
= '!' value:atom { return !value; } 
/atom 

atom 
= acs_check 
/'(' value:expr ')' { return value; } 

acs_check 
= n:name a:arg { return check(n, a); } 

name 
= c:([A-Z][A-Z]) { return c.join(''); } 

arg 
= c:[A-Z]+ { return c.join(''); } 
/d:[0-9]+ { return d.join(''); }