2

我正在尝试使用ParseKit创建一个严格的 CSS 解析器,它支持像 SASS 和 LESS 中的嵌套规则。我正在尝试适应和学习示例CSSJSON语法来构建我的语法。

到目前为止的语法:

@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

为什么这个语法在找到嵌套选择器时会停止解析?如何让它正确解析整个样式表?如何跟踪每个选择器和规则的祖先?

信息: 是我设置 PKParser 和委托选择器的课程。

4

0 回答 0