[英]Access Control String (ACS) Parser/Interpreter with PEG.js
前言
我正在努力創建一個帶有PEG.js的A ccess C ontrol S tring(或S ystem)(ACS)字符串解析器/解釋器。 ACS字符串通常用於公告板系統(BBS),以檢查對電路板特定區域的訪問權限。 例如,請參閱Renegade的ACS文檔 。
示例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”)應該進行方法調用以執行臟工作。
這是一個快速演示,可以正確解析您的示例輸入,並展示如何動態評估表達式(將返回一個布爾值):
{
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(''); }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.