private LessNode Parse(string input, Func <LessParser, RuleContext> parseFunc) { var lexer = new LessLexer(new AntlrInputStream(input)); var tokenStream = new CommonTokenStream(lexer); var parser = new LessParser(tokenStream); return(parseFunc(parser).Accept(new SyntaxTreeToParseTreeVisitor(tokenStream, isReference: false))); }
private string FindFile(IEnumerable<string> extensions, out int position) { LessParser parser = new LessParser(); string root = ProjectHelpers.GetProjectFolder(TextView.TextBuffer.GetFileName()); position = -1; string result = null; foreach (string ext in extensions) { foreach (string file in Directory.GetFiles(root, "*" + ext, SearchOption.AllDirectories)) { if (file.EndsWith(".min" + ext, StringComparison.OrdinalIgnoreCase)) continue; string text = File.ReadAllText(file); int index = text.IndexOf("." + _className, StringComparison.Ordinal); if (index > -1) { var css = parser.Parse(text, true); var visitor = new CssItemCollector<ClassSelector>(false); css.Accept(visitor); var selectors = visitor.Items.Where(c => c.ClassName.Text == _className); var high = selectors.FirstOrDefault(c => c.FindType<AtDirective>() == null && (c.Parent.NextSibling == null || c.Parent.NextSibling.Text == ",")); if (high != null) { position = high.Start; return file; } var medium = selectors.FirstOrDefault(c => c.Parent.NextSibling == null || c.Parent.NextSibling.Text == ","); if (medium != null) { position = medium.Start; result = file; continue; } var low = selectors.FirstOrDefault(); if (low != null) { position = low.Start; result = file; continue; } } } } return result; }
public Stylesheet Parse(string fileName, Stream input, bool isReference) { var charStream = new AntlrInputStream(input); var lexer = new LessLexer(charStream); var tokenStream = new CommonTokenStream(lexer); var parser = new LessParser(tokenStream) { ErrorHandler = new BailErrorStrategy() }; try { var lessStylesheet = parser.stylesheet(); return((Stylesheet)lessStylesheet.Accept(new SyntaxTreeToParseTreeVisitor(tokenStream, isReference))); } catch (ParseCanceledException ex) when(ex.InnerException is InputMismatchException ime) { throw ParserException.FromToken(fileName, ime.OffendingToken); } catch (ParseCanceledException ex) when(ex.InnerException is NoViableAltException nvae) { throw ParserException.FromToken(fileName, nvae.OffendingToken); } }
public static bool Parse(SyntaxContext context, int position) { var list = context.list; var offset = 0; var index = position; var count = 0; var isMissed = false; if (!ParserHelper.IsOperator(list[index], "[")) { return(false); } else { // ignored } offset += 1; index = position + offset; while (FunctionAParser.Parse(context, index)) { ; } while (ParenParser.Parse(context, index)) { ; } while (TableIParser.Parse(context, index)) { ; } while (TableSParser.Parse(context, index)) { ; } while (ListParser.Parse(context, index)) { ; } while (PropertyParser.Parse(context, index)) { ; } while (IndexParser.Parse(context, index)) { ; } while (CallParser.Parse(context, index)) { ; } while (NotParser.Parse(context, index)) { ; } while (LengthParser.Parse(context, index)) { ; } while (NegateParser.Parse(context, index)) { ; } while (PowerParser.Parse(context, index)) { ; } while (MultiplyParser.Parse(context, index)) { ; } while (DivisionParser.Parse(context, index)) { ; } while (ModParser.Parse(context, index)) { ; } while (AddParser.Parse(context, index)) { ; } while (SubtractParser.Parse(context, index)) { ; } while (ConcatParser.Parse(context, index)) { ; } while (LessParser.Parse(context, index)) { ; } while (GreaterParser.Parse(context, index)) { ; } while (LessEqualParser.Parse(context, index)) { ; } while (GreaterEqualParser.Parse(context, index)) { ; } while (EqualParser.Parse(context, index)) { ; } while (NotEqualParser.Parse(context, index)) { ; } while (AndParser.Parse(context, index)) { ; } while (OrParser.Parse(context, index)) { ; } if (!list[index].isRightValue) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsOperator(list[index], "]")) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsOperator(list[index], "=")) { return(false); } else { // ignored } offset += 1; index = position + offset; while (FunctionAParser.Parse(context, index)) { ; } while (ParenParser.Parse(context, index)) { ; } while (TableIParser.Parse(context, index)) { ; } while (TableSParser.Parse(context, index)) { ; } while (ListParser.Parse(context, index)) { ; } while (PropertyParser.Parse(context, index)) { ; } while (IndexParser.Parse(context, index)) { ; } while (CallParser.Parse(context, index)) { ; } while (NotParser.Parse(context, index)) { ; } while (LengthParser.Parse(context, index)) { ; } while (NegateParser.Parse(context, index)) { ; } while (PowerParser.Parse(context, index)) { ; } while (MultiplyParser.Parse(context, index)) { ; } while (DivisionParser.Parse(context, index)) { ; } while (ModParser.Parse(context, index)) { ; } while (AddParser.Parse(context, index)) { ; } while (SubtractParser.Parse(context, index)) { ; } while (ConcatParser.Parse(context, index)) { ; } while (LessParser.Parse(context, index)) { ; } while (GreaterParser.Parse(context, index)) { ; } while (LessEqualParser.Parse(context, index)) { ; } while (GreaterEqualParser.Parse(context, index)) { ; } while (EqualParser.Parse(context, index)) { ; } while (NotEqualParser.Parse(context, index)) { ; } while (AndParser.Parse(context, index)) { ; } while (OrParser.Parse(context, index)) { ; } if (!list[index].isRightValue) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsOperator(list[index], ",")) { isMissed = true; context.isMissed = true; } else { // ignored } offset += 1; index = position + offset; if (isMissed) { offset -= 1; } context.Insert(position, ExpressionCreator.CreateKV2(list, position, offset)); context.Remove(position + 1, offset); if (isMissed) { return(false); } return(true); }
public void TestMixinExpansion() { var lessCode = @" a { .myMixin(@p) { b, code { } } }"; var lessDoc = new LessParser().Parse(lessCode, false); var lessBlocks = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(lessDoc).ToList(); // Remove all but the deepest blocks while (0 < lessBlocks.RemoveAll(c => lessBlocks.Any(c.IsParentOf))) ; var literalExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal)).ToList(); CollectionAssert.AreEqual(new[] { "a .myMixin(@p) b", "a .myMixin(@p) code" }, literalExpansions); var skipExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Skip)).ToList(); CollectionAssert.AreEqual(new string[0], skipExpansions); var nestedExpansions = lessBlocks.SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.NestedOnly)).ToList(); CollectionAssert.AreEqual(new[] { "«mixin .myMixin» b", "«mixin .myMixin» code" }, nestedExpansions); }
public async Task SelectorExpansionTest() { #region LESS sources var testSources = new[]{ @" @media all { a { @media all { @media all { b { color: goldenrod; em { color: goldenrod; } } } } } } ", @" // Taken from http://blog.slaks.net/2013-09-29/less-css-secrets-of-the-ampersand/ a { color: blue; &:hover { color: green; } } form a { color: purple; body.QuietMode & { color: black; } } .quoted-source { background: #fcc; blockquote& { background: #fdc; } } .btn.btn-primary.btn-lg[disabled] { & + & + & { margin-left: 10px; } } p, blockquote, ul, li { border-top: 1px solid gray; & + & { border-top: 0; } } ", @" // Taken from https://github.com/less/less.js/blob/master/test/less/selectors.less h1, h2, h3 { a, p { &:hover { color: red; } } } #all { color: blue; } #the { color: blue; } #same { color: blue; } ul, li, div, q, blockquote, textarea { margin: 0; } td { margin: 0; padding: 0; } td, input { line-height: 1em; } a { color: red; &:hover { color: blue; } div & { color: green; } p & span { color: yellow; } } .foo { .bar, .baz { & .qux { display: block; } .qux & { display: inline; } .qux& { display: inline-block; } .qux & .biz { display: none; } } } .b { &.c { .a& { color: red; } } } .b { .c & { &.a { color: red; } } } .p { .foo &.bar { color: red; } } .p { .foo&.bar { color: red; } } .foo { .foo + & { background: amber; } & + & { background: amber; } } .foo, .bar { & + & { background: amber; } } .foo, .bar { a, b { & > & { background: amber; } } } .other ::fnord { color: red } .other::fnord { color: red } .other { ::bnord {color: red } &::bnord {color: red } } ", @"// Taken from https://github.com/less/less.js/blob/master/test/less/rulesets.less #first > .one { > #second .two > #deux { width: 50%; #third { &:focus { color: black; #fifth { > #sixth { .seventh #eighth { + #ninth { color: purple; } } } } } height: 100%; } #fourth, #five, #six { color: #110000; .seven, .eight > #nine { border: 1px solid black; } #ten { color: red; } } } font-size: 2em; } "}; #endregion foreach (var lessCode in testSources) { var cssCode = await CompileLess(lessCode); var lessDoc = new LessParser().Parse(lessCode, false); var cssDoc = new CssParser().Parse(cssCode, false); var cssSelectors = new CssItemAggregator<string>(false) { (Selector s) => CssExtensions.SelectorText(s) }.Crawl(cssDoc); var lessSelectors = new CssItemAggregator<RuleSet>(true) { (RuleSet rs) => rs }.Crawl(lessDoc) .Where(rs => rs.Block.Declarations.Any()) // Skip selectors that don't have any rules; these won't end up in the CSS .SelectMany(rs => LessDocument.GetSelectorNames(rs, LessMixinAction.Literal)) .ToList(); CollectionAssert.AreEqual(cssSelectors, lessSelectors); } }
public static bool Parse(SyntaxContext context, int position) { var list = context.list; var offset = 0; var index = position; var count = 0; var isMissed = false; if (!ParserHelper.IsKeyword(list[index], "if")) { return(false); } else { // ignored } offset += 1; index = position + offset; while (FunctionAParser.Parse(context, index)) { ; } while (ParenParser.Parse(context, index)) { ; } while (TableIParser.Parse(context, index)) { ; } while (TableSParser.Parse(context, index)) { ; } while (ListParser.Parse(context, index)) { ; } while (PropertyParser.Parse(context, index)) { ; } while (IndexParser.Parse(context, index)) { ; } while (CallParser.Parse(context, index)) { ; } while (NotParser.Parse(context, index)) { ; } while (LengthParser.Parse(context, index)) { ; } while (NegateParser.Parse(context, index)) { ; } while (PowerParser.Parse(context, index)) { ; } while (MultiplyParser.Parse(context, index)) { ; } while (DivisionParser.Parse(context, index)) { ; } while (ModParser.Parse(context, index)) { ; } while (AddParser.Parse(context, index)) { ; } while (SubtractParser.Parse(context, index)) { ; } while (ConcatParser.Parse(context, index)) { ; } while (LessParser.Parse(context, index)) { ; } while (GreaterParser.Parse(context, index)) { ; } while (LessEqualParser.Parse(context, index)) { ; } while (GreaterEqualParser.Parse(context, index)) { ; } while (EqualParser.Parse(context, index)) { ; } while (NotEqualParser.Parse(context, index)) { ; } while (AndParser.Parse(context, index)) { ; } while (OrParser.Parse(context, index)) { ; } if (!list[index].isRightValue) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsKeyword(list[index], "then")) { return(false); } else { // ignored } offset += 1; index = position + offset; while (ModuleParser.Parse(context, index)) { ; } if (list[index].type != Expression.Type.Module) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsKeyword(list[index], "else")) { return(false); } else { // ignored } offset += 1; index = position + offset; while (ModuleParser.Parse(context, index)) { ; } if (list[index].type != Expression.Type.Module) { return(false); } else { // ignored } offset += 1; index = position + offset; if (!ParserHelper.IsKeyword(list[index], "end")) { return(false); } else { // ignored } offset += 1; index = position + offset; context.Insert(position, ExpressionCreator.CreateIfElse(list, position, offset)); context.Remove(position + 1, offset); return(true); }