PageRenderTime 25ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/PropertyLists/Parser.cs

https://bitbucket.org/VahidN/interlace
C# | 183 lines | 108 code | 42 blank | 33 comment | 19 complexity | 224918bf9a71986c97cbed39149b3e65 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. #endregion
  31. namespace Interlace.PropertyLists
  32. {
  33. class Parser
  34. {
  35. public static object Parse(Lexer lexer)
  36. {
  37. return ParseObject(lexer, Token.None);
  38. }
  39. static object ParseObject(Lexer lexer, Token savedToken)
  40. {
  41. Token token = savedToken.Kind == TokenKind.None ? lexer.Next() : savedToken;
  42. // TODO: This should be done properly instead of just assuming it's a date time.
  43. // Date Time handling.
  44. //DateTime possibleDateValue;
  45. //if (token.Value is string && token.Kind == TokenKind.Literal &&
  46. // DateTime.TryParse(token.Value as string, out possibleDateValue))
  47. //{
  48. // return possibleDateValue;
  49. //}
  50. switch (token.Kind)
  51. {
  52. case TokenKind.Literal:
  53. return token.Value;
  54. case TokenKind.ArrayOpen:
  55. return ParseArray(lexer);
  56. case TokenKind.DictionaryOpen:
  57. return ParseDictionary(lexer);
  58. case TokenKind.DictionaryClose:
  59. case TokenKind.ArrayClose:
  60. case TokenKind.Equals:
  61. case TokenKind.Separator:
  62. case TokenKind.End:
  63. default:
  64. ThrowBecauseOfAnUnexpectedToken(lexer, token);
  65. return null;
  66. }
  67. }
  68. private static object ParseDictionary(Lexer lexer)
  69. {
  70. PropertyDictionary dictionary = new PropertyDictionary();
  71. while (true)
  72. {
  73. Token token = lexer.Next();
  74. if (token.Kind == TokenKind.DictionaryClose) break;
  75. object key = ParseObject(lexer, token);
  76. Token equals = lexer.Next();
  77. if (equals.Kind != TokenKind.Equals) ThrowBecauseOfAnUnexpectedToken(lexer, equals);
  78. object value = ParseObject(lexer, Token.None);
  79. dictionary.SetValueFor(key, value);
  80. Token terminator = lexer.Next();
  81. if (terminator.Kind == TokenKind.DictionaryClose) break;
  82. if (terminator.Kind == TokenKind.Separator) continue;
  83. ThrowBecauseOfAnUnexpectedToken(lexer, terminator);
  84. }
  85. return dictionary;
  86. }
  87. private static object ParseArray(Lexer lexer)
  88. {
  89. PropertyArray array = new PropertyArray();
  90. while (true)
  91. {
  92. Token token = lexer.Next();
  93. if (token.Kind == TokenKind.ArrayClose) break;
  94. object value = ParseObject(lexer, token);
  95. array.AppendValue(value);
  96. Token terminator = lexer.Next();
  97. if (terminator.Kind == TokenKind.ArrayClose) break;
  98. if (terminator.Kind == TokenKind.Separator) continue;
  99. ThrowBecauseOfAnUnexpectedToken(lexer, terminator);
  100. }
  101. return array;
  102. }
  103. static void ThrowBecauseOfAnUnexpectedToken(Lexer lexer, Token token)
  104. {
  105. string description = "";
  106. switch (token.Kind)
  107. {
  108. case TokenKind.Literal:
  109. description = "literal";
  110. break;
  111. case TokenKind.ArrayOpen:
  112. description = "array opening character";
  113. break;
  114. case TokenKind.ArrayClose:
  115. description = "array closing character";
  116. break;
  117. case TokenKind.DictionaryOpen:
  118. description = "dictionary opening character";
  119. break;
  120. case TokenKind.DictionaryClose:
  121. description = "dictionary closing character";
  122. break;
  123. case TokenKind.Equals:
  124. description = "equals character";
  125. break;
  126. case TokenKind.Separator:
  127. description = "separator character";
  128. break;
  129. case TokenKind.End:
  130. description = "end of file";
  131. break;
  132. default:
  133. description = "unknown token";
  134. break;
  135. }
  136. throw new PropertyListException(string.Format(
  137. "An unexpected {0} was found on line {1} of the configuration " +
  138. "file \"{2}\".", description, token.LineNumber, lexer.NameForExceptions));
  139. }
  140. }
  141. }