我正在尝试使用ParseKit创建一个严格的CSS解析器,它支持嵌套规则,例如在SASS和LESS中找到的规则。我正在尝试调整并学习样本CSS和JSON语法来构建我的语法。
到目前为止的语法:
@symbols = '//';
@singleLineComments = '//';
@multiLineComments = '/*' '*/';
@wordState = '-' '@';
@start
@before {
PKTokenizer *t = self.tokenizer;
// symbols
[t.symbolState add:@"/*"];
[t.symbolState add:@"*/"];
[t.symbolState add:@"//"];
[t.symbolState add:@"url("];
[t.symbolState add:@"URL("];
[t.symbolState add:@"Url("];
// word chars -moz, -webkit, @media, #id, .class, :hover
[t setTokenizerState:t.wordState from:'-' to:'-'];
[t setTokenizerState:t.wordState from:'@' to:'@'];
[t setTokenizerState:t.wordState from:'.' to:'.'];
[t setTokenizerState:t.wordState from:'#' to:'#'];
[t.wordState setWordChars:YES from:'-' to:'-'];
[t.wordState setWordChars:YES from:'@' to:'@'];
[t.wordState setWordChars:YES from:'.' to:'.'];
[t.wordState setWordChars:YES from:'#' to:'#'];
// comments
[t setTokenizerState:t.commentState from:'/' to:'/'];
[t.commentState setFallbackState:t.symbolState from:'/' to:'/'];
[t.commentState addSingleLineStartMarker:@"//"];
[t.commentState addMultiLineStartMarker:@"/*" endMarker:@"*/"];
t.commentState.reportsCommentTokens = YES;
// urls
[t setTokenizerState:t.delimitState from:'u' to:'u'];
[t setTokenizerState:t.delimitState from:'U' to:'U'];
[t.delimitState addStartMarker:@"url(" endMarker:@")" allowedCharacterSet:nil];
[t.delimitState addStartMarker:@"URL(" endMarker:@")" allowedCharacterSet:nil];
[t.delimitState addStartMarker:@"Url(" endMarker:@")" allowedCharacterSet:nil];
}
= ruleset*;
ruleset = selectors openCurly ( decls | selector ) closeCurly;
selectors = selector commaSelector*;
selector = (selectorWord | hashSym | dot | colon | gt | openBracket | closeBracket | eq | selectorQuotedString | tilde | pipe)+;
selectorWord = Word;
selectorQuotedString = QuotedString;
commaSelector = comma selector;
decls = Empty | actualDecls;
actualDecls = decl decl*;
decl = property colon expr important? semi;
property = Word;
expr = (string | constant | num | url | openParen | closeParen | comma | nonTerminatingSymbol)+;
url = urlLower | urlUpper;
urlLower = %{'url(', ')'};
urlUpper = %{'URL(', ')'};
nonTerminatingSymbol = {return NE(LS(1), @";") && NE(LS(1), @"!");}? fwdSlash | Symbol;
important = bang Word;
string = QuotedString;
constant = Word;
openCurly = '{';
closeCurly = '}';
openBracket = '[';
closeBracket = ']';
eq = '=';
comma = ',';
colon = ':';
semi = ';';
openParen = '(';
closeParen = ')';
gt = '>';
tilde = '~';
pipe = '|';
fwdSlash = '/';
hashSym = '#';
dot = '.';
at = '@';
bang = '!';
num = Number;
我认为启用嵌套规则的关键是
ruleset = selectors openCurly ( decls | selector ) closeCurly;
行,允许像JSON语法那样的嵌套选择器。但是当我输入像
这样的字符串时.myClass1 {
.content {}
}
.myClass2 {}
汇编堆栈仅显示['.', 'myClass1', '.', 'content']
。它似乎完全跳过.myClass2
。
为什么这个语法在找到嵌套选择器时会停止解析?如何正确解析整个样式表?如何跟踪每个选择器和规则的祖先?
信息 here是我的类,用于设置PKParser和委托选择器。