public override ExpressionNode Resolve(ScopeNode scope) { var a = A.Resolve(scope) as ValueNode; var b = B.Resolve(scope) as ValueNode; if (a == null || b == null) throw new InvalidOperationException("Can only combine values"); switch (CombineOperator) { case '*': return a*b; case '+': return a + b; case '-': return a - b; case '/': return a/b; case '=': return ValueNode.ValueEquals(a, b); case '<': return a < b; case '>': return a > b; } throw new Exception($"Invalid operator: {CombineOperator}"); }
public override ExpressionNode Resolve(ScopeNode scope) { var args = ValueList.From(_args.Resolve(scope)); switch (Name) { case "nth": { var vs = ValueList.From(args[0]); var index = (int) args[1]; return vs[index - 1]; } case "map-get": { var vs = ValueList.From(args[0]); var key = (string) args[1]; return vs[key]; } } var function = scope.GetFunction(Name); var result = function.Execute(args); return result; }
public ScopeNode GetActiveScope(ScopeNode currentScope) { if (Test(currentScope)) return this; foreach (var elseNode in Elses) { if (elseNode.Test(currentScope)) return elseNode; } return null; }
private void ReadFor(ScopeNode currentScope) { Expect('$'); var varName = ReadName(); Expect("from"); SkipWhitespace(); var from = ReadValueList('t'); Expect("through"); SkipWhitespace(); var through = ReadValueList('{'); Expect('{'); var node = new ForNode(new VariableNode(varName), new Expression(from), new Expression(through)); currentScope.Add(node); ReadScopeContent(node); }
private void ReadReturn(ScopeNode currentScope) { ExpressionNode value = ReadValueList(';'); Expect(';'); var result = new ReturnNode(new Expression(value)); currentScope.Add(result); }
private void ReadScopeContent(ScopeNode currentScope) { var buffer = new StringBuilder(); var interpolations = new List<ValueList>(); //States var inCommentStart = false; var paranthesesLevel = 0; var inDoubleQuotes = false; while (!EndOfStream) { var c = (char) Read(); if (inDoubleQuotes) { buffer.Append(c); if (c == '"') { inDoubleQuotes = false; } } else { switch (c) { case ' ': //Ignore starting white space if (buffer.Length == 0) break; goto default; case '@': if (buffer.Length != 0) throw new Exception("Must be first character"); ReadAt(currentScope); break; case '$': var name = ReadUntil(':'); var vn = new VariableNode(name); vn.Expression = new Expression(ReadValueList(';')); Expect(';'); currentScope.Add(vn); break; case '/': if (inCommentStart) { ReadInlineComment(); inCommentStart = false; //Remove the first slash from the buffer buffer.Length--; } else { buffer.Append(c); inCommentStart = true; } break; case '*': if (inCommentStart) { var node = ReadComment(); currentScope.Add(node); inCommentStart = false; //Remove the first slash from the buffer buffer.Length--; break; } goto default; case ';': { throw new ScssReaderException("Unexpected ;", File.Path, _lineNumber); } case ':': var pc = (char) Peek(); if (char.IsLetter(pc)) //hover etc. { buffer.Append(c); } else if (pc == ':') { buffer.Append(c); buffer.Append(pc); Read(); } else { var pn = new PropertyNode(); pn.Name = new ScssString(buffer.ToString().Trim(), interpolations); pn.Expression = new Expression(ReadValueList(';', '{')); buffer.Clear(); var pc2 = (char) Read(); if (pc2 == ';') { currentScope.Add(pn); } else if (pc2 == '{') { var result = new NamespaceNode(pn); ReadScopeContent(result); currentScope.Add(result); } else { throw new ScssReaderException("Expected { or ;", File.Path, _lineNumber); } } break; case '"': inDoubleQuotes = true; goto default; case '(': paranthesesLevel++; goto default; case ')': paranthesesLevel--; goto default; case '{': { var node = new SelectorNode(); node.Selector = new ScssString(buffer.ToString().Trim(), interpolations); ReadScopeContent(node); currentScope.Add(node); buffer.Clear(); } break; case '}': return; case '#': if (Peek() == '{') { inCommentStart = false; var value = ReadInterpolation(); buffer.Append("{" + interpolations.Count + "}"); interpolations.Add(value); break; } else { goto default; } case '\n': inCommentStart = false; break; default: inCommentStart = false; buffer.Append(c); break; } } } }
private void ReadMedia(ScopeNode currentScope) { var def = ReadUntil('{'); MediaNode node = new MediaNode() { Definition = def.TrimEnd() }; ReadScopeContent(node); currentScope.Add(node); }
private void ReadMixin(ScopeNode currentScope) { var name = ReadName(); VariableNode[] args = new VariableNode[0]; SkipWhitespace(); if (Peek() == '(') args = ReadArgumentDefinition().ToArray(); var node = new MixinNode(name, args); Expect('{'); ReadScopeContent(node); currentScope.Add(node); }
public string Resolve(ScopeNode scope) { object[] args = _interpolations.Select(x => x.Resolve(scope)).ToArray(); return string.Format(_value, args); }
private void ReadInclude(ScopeNode currentScope) { var name = ReadName(); ValueList args = new ValueList(); SkipWhitespace(); if (Peek() == '(') args = ReadArgumentCall(); SkipWhitespace(); var result = new IncludeNode(name, args); currentScope.Add(result); if (Peek() == '{') { Expect('{'); ReadScopeContent(result); } else Optional(';'); }
private void ProcessImport(string path, ScssPackage fromPackage, ScopeNode scope, CssRoot root, CssSelector selector, int level, string nspace = "") { var file = fromPackage.File.SolveReference(path); var tree = TreeFromFile(file); ProcessScope(tree, tree, root, selector, level, nspace); }
public ExpressionNode Resolve(ScopeNode scope) { return Root.Resolve(scope); }
private void ReadExtend(ScopeNode currentScope) { string selector = ReadUntil(';'); currentScope.Add(new ExtendNode(selector)); }
public abstract ExpressionNode Resolve(ScopeNode scope);
private void ReadElse(ScopeNode currentScope) { ElseNode elseNode; if (Peek() == 'i') //Assume if { Read(); Expect('f'); SkipWhitespace(); var val = ReadValueList('{'); Expect('{'); elseNode = new ElseNode(val); } else { elseNode = new ElseNode(); } var parentIf = currentScope.Nodes.Last() as IfNode; if (parentIf == null) throw new Exception("Else without if"); parentIf.Elses.Add(elseNode); ReadScopeContent(elseNode); }
private void ReadEach(ScopeNode currentScope) { var varNames = ReadValueList('i'); Expect("in"); var val = ReadValueList('{'); Expect('{'); var node = new EachNode(varNames, val); currentScope.Add(node); ReadScopeContent(node); }
private void ReadContent(ScopeNode currentScope) { currentScope.Add(new ContentNode()); Optional(';'); }
private void ReadAt(ScopeNode currentScope) { string type = ReadName(); SkipWhitespace(); switch (type) { case "media": ReadMedia(currentScope); break; case "mixin": ReadMixin(currentScope); break; case "content": ReadContent(currentScope); break; case "include": ReadInclude(currentScope); break; case "import": ReadImport(currentScope); break; case "function": ReadFunction(currentScope); break; case "return": ReadReturn(currentScope); break; case "if": ReadIf(currentScope); break; case "else": ReadElse(currentScope); break; case "each": ReadEach(currentScope); break; case "for": ReadFor(currentScope); break; case "extend": ReadExtend(currentScope); break; default: throw new ScssReaderException($"Could not recognize @{type}", File.Path, _lineNumber); } }
public override ExpressionNode Resolve(ScopeNode scope) { return scope.GetVariable(VariableName).Expression.Resolve(scope); }
private void ProcessScope(ScssPackage package, ScopeNode scope, CssRoot root, CssSelector selector, int level, string nspace = "") { if (scope is SelectorNode) { var snode = (SelectorNode) scope; var s = snode.Selector.Resolve(scope); if (selector != null) { s = ExpandSelector(selector.Selector, s); } selector = new CssSelector(s, level); root.Add(selector); } foreach (var node in scope.Nodes) { var useNode = node; if (node is PropertyNode) { var n = (PropertyNode) node; var value = n.Expression.Resolve(scope).Value; selector.Add(new CssProperty(nspace + n.Name.Resolve(scope), value, level + 1)); } else if (node is MediaNode) { var n = (MediaNode) node; var s = new CssMedia(level + 1) { Definition = n.Definition }; root.Add(s); int nextLevel = level + 1; if (selector != null) { selector = new CssSelector(selector.Selector, level + 2); s.Add(selector); nextLevel++; } ProcessScope(package, (ScopeNode) n, s, selector, nextLevel, nspace); } else if (node is CommentNode) { var n = (CommentNode) node; CssNode p = root; if (selector != null) p = selector; p.Add(new CssComment(n.Comment, level + 1)); } else if (node is ImportNode) { var n = (ImportNode) node; if (n.Path.Contains(".css") || n.Path.Contains("http://") || n.Path.Contains("url(") || n.Path.Contains(" ")) { root.Add(new CssImport(n.Path, level + 1)); } else { var path = n.Path.Trim('\"'); ProcessImport(path, package, scope, root, selector, level, nspace); } } else if (node is VariableNode) { var n = (VariableNode) node; scope.SetVariable(n); } else if (node is MixinNode) { var n = (MixinNode) node; scope.SetMixin(n); } else if (node is ContentNode) { var sn = scope.GetContent(); ProcessScope(package, sn, root, selector, level - 1, nspace); } else if (node is IfNode) { var n = (IfNode) node; var sn = n.GetActiveScope(scope); if (sn != null) ProcessScope(package, sn, root, selector, level, nspace); } else if (node is EachNode) { var n = (EachNode) node; var var = n.Variables; foreach (var value in n.List) { if (var.Count == 1) { var[0].Expression = new Expression(value); n.SetVariable(var[0]); } else { if (!(value is ValueList)) throw new Exception("This must be a list"); var subList = (ValueList) value; // There is a bug in the reader causing unecessary levels of value lists // TODO UNDONE if (subList.Count == 1) subList = (ValueList) subList[0]; for (int i = 0; i < var.Count; i++) { var[i].Expression = new Expression(subList[i]); n.SetVariable(var[i]); } } ProcessScope(package, n, root, selector, level, nspace); } } else if (node is ForNode) { var n = (ForNode) node; var var = n.Variable; int from = int.Parse(n.From.Resolve(scope).Value); int to = 0; string toStr = n.Through.Resolve(scope).Value; if (!int.TryParse(toStr, out to)) throw new Exception("Failed to parse to value"); for (int i = from; i <= to; i++) { var value = new ValueNode(i.ToString()); var.Expression = new Expression(value); n.SetVariable(var); ProcessScope(package, n, root, selector, level, nspace); } } else if (node is ExtendNode) { var n = (ExtendNode) node; package.AddExtension(new ScssExtension() { Selector = selector.Selector, Super = ((ExtendNode) node).Selector }); } else if (node is FunctionNode) { var n = (FunctionNode) node; scope.SetFunction(n); } else if (node is NamespaceNode) { var subLevel = level; var n = (NamespaceNode) node; string header = n.Header.Name.Resolve(scope); if (!n.Header.Expression.Empty) { var value = n.Header.Expression.Resolve(scope).Value; selector.Add(new CssProperty(header, value, level + 1)); subLevel++; } ProcessScope(package, (ScopeNode) node, root, selector, subLevel, header + "-"); } else if (node is IncludeNode) { var n = (IncludeNode) node; var mn = scope.GetMixin(n.MixinName); mn.Initialize(n); ProcessScope(package, mn, root, selector, level); } else if (useNode is SelectorNode) { ProcessScope(package, (ScopeNode) node, root, selector, level + 1); } } }
private void ReadFunction(ScopeNode currentScope) { var name = ReadName(); var args = ReadArgumentDefinition(); var node = new FunctionNode(name, args.ToArray()); Expect('{'); ReadScopeContent(node); currentScope.Add(node); }
private void ReadIf(ScopeNode currentScope) { var val = ReadValueList('{'); Expect('{'); var ifNode = new IfNode(val); currentScope.Add(ifNode); ReadScopeContent(ifNode); }
private void ReadImport(ScopeNode currentScope) { var path = ReadUntil(';'); currentScope.Add(new ImportNode(path)); }
public bool Test(ScopeNode currentScope) { var result = _condition.Resolve(currentScope); return result.Value == "1"; }
public virtual void SetContent(ScopeNode content) { _content = content; }