Parser.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. using ExCSS.Model;
  5. using ExCSS.Model.TextBlocks;
  6. // ReSharper disable once CheckNamespace
  7. using System;
  8. //The MIT License (MIT)
  9. //Copyright (c) [year] [fullname]
  10. //Permission is hereby granted, free of charge, to any person obtaining a copy
  11. //of this software and associated documentation files (the "Software"), to deal
  12. //in the Software without restriction, including without limitation the rights
  13. //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. //copies of the Software, and to permit persons to whom the Software is
  15. //furnished to do so, subject to the following conditions:
  16. //The above copyright notice and this permission notice shall be included in all
  17. //copies or substantial portions of the Software.
  18. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. //SOFTWARE.
  25. #pragma warning disable
  26. namespace ExCSS
  27. {
  28. internal delegate void ParseErrorEventHandler(StylesheetParseError e);
  29. public sealed partial class Parser
  30. {
  31. private SelectorFactory _selectorFactory;
  32. private Stack<FunctionBuffer> _functionBuffers;
  33. private Lexer _lexer;
  34. private bool _isFraction;
  35. private Property _property;
  36. private TermList _terms = new TermList();
  37. private StyleSheet _styleSheet;
  38. private Stack<RuleSet> _activeRuleSets;
  39. private StringBuilder _buffer;
  40. private ParsingContext _parsingContext;
  41. public StyleSheet Parse(string css)
  42. {
  43. _selectorFactory = new SelectorFactory();
  44. _functionBuffers = new Stack<FunctionBuffer>();
  45. _styleSheet = new StyleSheet();
  46. _activeRuleSets = new Stack<RuleSet>();
  47. _lexer = new Lexer(new StylesheetReader(css)) { ErrorHandler = HandleLexerError };
  48. SetParsingContext(ParsingContext.DataBlock);
  49. var tokens = _lexer.Tokens;
  50. foreach (var token in tokens)
  51. {
  52. if (ParseTokenBlock(token))
  53. {
  54. continue;
  55. }
  56. HandleLexerError(ParserError.UnexpectedLineBreak, ErrorMessages.Default);
  57. }
  58. if (_property != null)
  59. {
  60. ParseTokenBlock(SpecialCharacter.Semicolon);
  61. }
  62. return _styleSheet;
  63. }
  64. internal static BaseSelector ParseSelector(string selector)
  65. {
  66. var tokenizer = new Lexer(new StylesheetReader(selector));
  67. var tokens = tokenizer.Tokens;
  68. var selctor = new SelectorFactory();
  69. foreach (var token in tokens)
  70. {
  71. selctor.Apply(token);
  72. }
  73. var result = selctor.GetSelector();
  74. return result;
  75. }
  76. internal static RuleSet ParseRule(string css)
  77. {
  78. var parser = new Parser();
  79. var styleSheet = parser.Parse(css);
  80. return styleSheet.Rules.Count > 0
  81. ? styleSheet.Rules[0]
  82. : null;
  83. }
  84. internal static StyleDeclaration ParseDeclarations(string declarations, bool quirksMode = false)
  85. {
  86. var decl = new StyleDeclaration();
  87. AppendDeclarations(decl, declarations, quirksMode);
  88. return decl;
  89. }
  90. internal static void AppendDeclarations(StyleDeclaration list, string css, bool quirksMode = false)
  91. {
  92. var parser = new Parser();//(new StyleSheet(), new StylesheetReader(declarations))
  93. parser.AddRuleSet(list.ParentRule ?? new StyleRule(list));
  94. parser._parsingContext = ParsingContext.InDeclaration;
  95. parser.Parse(css);
  96. }
  97. internal void HandleLexerError(ParserError error, string message)
  98. {
  99. _styleSheet.Errors.Add(new StylesheetParseError(error, message, _lexer.Stream.Line, _lexer.Stream.Column));
  100. }
  101. private bool AddTerm(Term value)
  102. {
  103. if (_isFraction)
  104. {
  105. if (_terms.Length > 0)
  106. {
  107. value = new PrimitiveTerm(UnitType.Unknown, _terms[0] + "/" + value);
  108. _terms = new TermList();
  109. }
  110. _isFraction = false;
  111. }
  112. if (_functionBuffers.Count > 0)
  113. {
  114. _functionBuffers.Peek().TermList.Add(value);
  115. }
  116. else if (_terms.Length == 0)
  117. {
  118. _terms.AddTerm(value);
  119. }
  120. else if (_parsingContext == ParsingContext.InSingleValue)
  121. {
  122. _terms.AddTerm(value);
  123. }
  124. else
  125. {
  126. return false;
  127. }
  128. return true;
  129. }
  130. private void FinalizeProperty()
  131. {
  132. if (_property != null)
  133. {
  134. if (_terms.Length > 1)
  135. {
  136. _property.Term = _terms;
  137. }
  138. else
  139. {
  140. _property.Term = _terms[0];
  141. }
  142. }
  143. _terms = new TermList();
  144. _property = null;
  145. }
  146. private bool FinalizeRule()
  147. {
  148. if (_activeRuleSets.Count <= 0)
  149. {
  150. return false;
  151. }
  152. _activeRuleSets.Pop();
  153. return true;
  154. }
  155. private void AddRuleSet(RuleSet rule)
  156. {
  157. //rule.ParentStyleSheet = _styleSheet;
  158. if (_activeRuleSets.Count > 0)
  159. {
  160. var container = _activeRuleSets.Peek() as ISupportsRuleSets;
  161. if (container != null)
  162. {
  163. container.RuleSets.Add(rule);
  164. }
  165. }
  166. else
  167. {
  168. _styleSheet.Rules.Add(rule);
  169. }
  170. _activeRuleSets.Push(rule);
  171. }
  172. private void AddProperty(Property property)
  173. {
  174. _property = property;
  175. var rule = CurrentRule as ISupportsDeclarations;
  176. if (rule != null)
  177. {
  178. rule.Declarations.Add(property);
  179. }
  180. }
  181. private T CastRuleSet<T>() where T : RuleSet
  182. {
  183. if (_activeRuleSets.Count > 0)
  184. {
  185. return _activeRuleSets.Peek() as T;
  186. }
  187. return default(T);
  188. }
  189. private void SetParsingContext(ParsingContext newState)
  190. {
  191. switch (newState)
  192. {
  193. case ParsingContext.InSelector:
  194. _lexer.IgnoreComments = true;
  195. _lexer.IgnoreWhitespace = false;
  196. _selectorFactory.ResetFactory();
  197. break;
  198. case ParsingContext.InHexValue:
  199. case ParsingContext.InUnknown:
  200. case ParsingContext.InCondition:
  201. case ParsingContext.InSingleValue:
  202. case ParsingContext.InMediaValue:
  203. _lexer.IgnoreComments = true;
  204. _lexer.IgnoreWhitespace = false;
  205. break;
  206. default:
  207. _lexer.IgnoreComments = true;
  208. _lexer.IgnoreWhitespace = true;
  209. break;
  210. }
  211. _parsingContext = newState;
  212. }
  213. internal RuleSet CurrentRule
  214. {
  215. get
  216. {
  217. return _activeRuleSets.Count > 0
  218. ? _activeRuleSets.Peek()
  219. : null;
  220. }
  221. }
  222. }
  223. }
  224. #pragma warning restore