The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. XmlTokeniser::XmlTokeniser() {}
  20. XmlTokeniser::~XmlTokeniser() {}
  21. CodeEditorComponent::ColourScheme XmlTokeniser::getDefaultColourScheme()
  22. {
  23. struct Type
  24. {
  25. const char* name;
  26. uint32 colour;
  27. };
  28. const Type types[] =
  29. {
  30. { "Error", 0xffcc0000 },
  31. { "Comment", 0xff00aa00 },
  32. { "Keyword", 0xff0000cc },
  33. { "Operator", 0xff225500 },
  34. { "Identifier", 0xff000000 },
  35. { "String", 0xff990099 },
  36. { "Bracket", 0xff000055 },
  37. { "Punctuation", 0xff004400 },
  38. { "Preprocessor Text", 0xff660000 }
  39. };
  40. CodeEditorComponent::ColourScheme cs;
  41. for (unsigned int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2)
  42. cs.set (types[i].name, Colour (types[i].colour));
  43. return cs;
  44. }
  45. template <typename Iterator>
  46. static void skipToEndOfXmlDTD (Iterator& source) noexcept
  47. {
  48. bool lastWasQuestionMark = false;
  49. for (;;)
  50. {
  51. const juce_wchar c = source.nextChar();
  52. if (c == 0 || (c == '>' && lastWasQuestionMark))
  53. break;
  54. lastWasQuestionMark = (c == '?');
  55. }
  56. }
  57. template <typename Iterator>
  58. static void skipToEndOfXmlComment (Iterator& source) noexcept
  59. {
  60. juce_wchar last[2] = { 0 };
  61. for (;;)
  62. {
  63. const juce_wchar c = source.nextChar();
  64. if (c == 0 || (c == '>' && last[0] == '-' && last[1] == '-'))
  65. break;
  66. last[1] = last[0];
  67. last[0] = c;
  68. }
  69. }
  70. int XmlTokeniser::readNextToken (CodeDocument::Iterator& source)
  71. {
  72. source.skipWhitespace();
  73. const juce_wchar firstChar = source.peekNextChar();
  74. switch (firstChar)
  75. {
  76. case 0: break;
  77. case '"':
  78. case '\'':
  79. CppTokeniserFunctions::skipQuotedString (source);
  80. return tokenType_string;
  81. case '<':
  82. {
  83. source.skip();
  84. source.skipWhitespace();
  85. const juce_wchar nextChar = source.peekNextChar();
  86. if (nextChar == '?')
  87. {
  88. source.skip();
  89. skipToEndOfXmlDTD (source);
  90. return tokenType_preprocessor;
  91. }
  92. if (nextChar == '!')
  93. {
  94. source.skip();
  95. if (source.peekNextChar() == '-')
  96. {
  97. source.skip();
  98. if (source.peekNextChar() == '-')
  99. {
  100. skipToEndOfXmlComment (source);
  101. return tokenType_comment;
  102. }
  103. }
  104. }
  105. CppTokeniserFunctions::skipIfNextCharMatches (source, '/');
  106. CppTokeniserFunctions::parseIdentifier (source);
  107. source.skipWhitespace();
  108. CppTokeniserFunctions::skipIfNextCharMatches (source, '/');
  109. source.skipWhitespace();
  110. CppTokeniserFunctions::skipIfNextCharMatches (source, '>');
  111. return tokenType_keyword;
  112. }
  113. case '>':
  114. source.skip();
  115. return tokenType_keyword;
  116. case '/':
  117. source.skip();
  118. source.skipWhitespace();
  119. CppTokeniserFunctions::skipIfNextCharMatches (source, '>');
  120. return tokenType_keyword;
  121. case '=':
  122. case ':':
  123. source.skip();
  124. return tokenType_operator;
  125. default:
  126. if (CppTokeniserFunctions::isIdentifierStart (firstChar))
  127. CppTokeniserFunctions::parseIdentifier (source);
  128. source.skip();
  129. break;
  130. };
  131. return tokenType_identifier;
  132. }