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.

241 lines
7.2KB

  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. namespace juce
  20. {
  21. struct LuaTokeniserFunctions
  22. {
  23. static bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept
  24. {
  25. static const char* const keywords2Char[] =
  26. { "if", "or", "in", "do", nullptr };
  27. static const char* const keywords3Char[] =
  28. { "and", "end", "for", "nil", "not", nullptr };
  29. static const char* const keywords4Char[] =
  30. { "then", "true", "else", nullptr };
  31. static const char* const keywords5Char[] =
  32. { "false", "local", "until", "while", "break", nullptr };
  33. static const char* const keywords6Char[] =
  34. { "repeat", "return", "elseif", nullptr};
  35. static const char* const keywordsOther[] =
  36. { "function", "@interface", "@end", "@synthesize", "@dynamic", "@public",
  37. "@private", "@property", "@protected", "@class", nullptr };
  38. const char* const* k;
  39. switch (tokenLength)
  40. {
  41. case 2: k = keywords2Char; break;
  42. case 3: k = keywords3Char; break;
  43. case 4: k = keywords4Char; break;
  44. case 5: k = keywords5Char; break;
  45. case 6: k = keywords6Char; break;
  46. default:
  47. if (tokenLength < 2 || tokenLength > 16)
  48. return false;
  49. k = keywordsOther;
  50. break;
  51. }
  52. for (int i = 0; k[i] != 0; ++i)
  53. if (token.compare (CharPointer_ASCII (k[i])) == 0)
  54. return true;
  55. return false;
  56. }
  57. template <typename Iterator>
  58. static int parseIdentifier (Iterator& source) noexcept
  59. {
  60. int tokenLength = 0;
  61. String::CharPointerType::CharType possibleIdentifier[100];
  62. String::CharPointerType possible (possibleIdentifier);
  63. while (CppTokeniserFunctions::isIdentifierBody (source.peekNextChar()))
  64. {
  65. auto c = source.nextChar();
  66. if (tokenLength < 20)
  67. possible.write (c);
  68. ++tokenLength;
  69. }
  70. if (tokenLength > 1 && tokenLength <= 16)
  71. {
  72. possible.writeNull();
  73. if (isReservedKeyword (String::CharPointerType (possibleIdentifier), tokenLength))
  74. return LuaTokeniser::tokenType_keyword;
  75. }
  76. return LuaTokeniser::tokenType_identifier;
  77. }
  78. template <typename Iterator>
  79. static int readNextToken (Iterator& source)
  80. {
  81. source.skipWhitespace();
  82. auto firstChar = source.peekNextChar();
  83. switch (firstChar)
  84. {
  85. case 0:
  86. break;
  87. case '0': case '1': case '2': case '3': case '4':
  88. case '5': case '6': case '7': case '8': case '9':
  89. case '.':
  90. {
  91. auto result = CppTokeniserFunctions::parseNumber (source);
  92. if (result == LuaTokeniser::tokenType_error)
  93. {
  94. source.skip();
  95. if (firstChar == '.')
  96. return LuaTokeniser::tokenType_punctuation;
  97. }
  98. return result;
  99. }
  100. case ',':
  101. case ';':
  102. case ':':
  103. source.skip();
  104. return LuaTokeniser::tokenType_punctuation;
  105. case '(': case ')':
  106. case '{': case '}':
  107. case '[': case ']':
  108. source.skip();
  109. return LuaTokeniser::tokenType_bracket;
  110. case '"':
  111. case '\'':
  112. CppTokeniserFunctions::skipQuotedString (source);
  113. return LuaTokeniser::tokenType_string;
  114. case '+':
  115. source.skip();
  116. CppTokeniserFunctions::skipIfNextCharMatches (source, '+', '=');
  117. return LuaTokeniser::tokenType_operator;
  118. case '-':
  119. {
  120. source.skip();
  121. auto result = CppTokeniserFunctions::parseNumber (source);
  122. if (source.peekNextChar() == '-')
  123. {
  124. source.skipToEndOfLine();
  125. return LuaTokeniser::tokenType_comment;
  126. }
  127. if (result == LuaTokeniser::tokenType_error)
  128. {
  129. CppTokeniserFunctions::skipIfNextCharMatches (source, '-', '=');
  130. return LuaTokeniser::tokenType_operator;
  131. }
  132. return result;
  133. }
  134. case '*': case '%':
  135. case '=': case '!':
  136. source.skip();
  137. CppTokeniserFunctions::skipIfNextCharMatches (source, '=');
  138. return LuaTokeniser::tokenType_operator;
  139. case '?':
  140. case '~':
  141. source.skip();
  142. return LuaTokeniser::tokenType_operator;
  143. case '<': case '>':
  144. case '|': case '&': case '^':
  145. source.skip();
  146. CppTokeniserFunctions::skipIfNextCharMatches (source, firstChar);
  147. CppTokeniserFunctions::skipIfNextCharMatches (source, '=');
  148. return LuaTokeniser::tokenType_operator;
  149. default:
  150. if (CppTokeniserFunctions::isIdentifierStart (firstChar))
  151. return parseIdentifier (source);
  152. source.skip();
  153. break;
  154. }
  155. return LuaTokeniser::tokenType_error;
  156. }
  157. };
  158. //==============================================================================
  159. LuaTokeniser::LuaTokeniser() {}
  160. LuaTokeniser::~LuaTokeniser() {}
  161. int LuaTokeniser::readNextToken (CodeDocument::Iterator& source)
  162. {
  163. return LuaTokeniserFunctions::readNextToken (source);
  164. }
  165. CodeEditorComponent::ColourScheme LuaTokeniser::getDefaultColourScheme()
  166. {
  167. static const CodeEditorComponent::ColourScheme::TokenType types[] =
  168. {
  169. { "Error", Colour (0xffcc0000) },
  170. { "Comment", Colour (0xff3c3c3c) },
  171. { "Keyword", Colour (0xff0000cc) },
  172. { "Operator", Colour (0xff225500) },
  173. { "Identifier", Colour (0xff000000) },
  174. { "Integer", Colour (0xff880000) },
  175. { "Float", Colour (0xff885500) },
  176. { "String", Colour (0xff990099) },
  177. { "Bracket", Colour (0xff000055) },
  178. { "Punctuation", Colour (0xff004400) }
  179. };
  180. CodeEditorComponent::ColourScheme cs;
  181. for (auto& t : types)
  182. cs.set (t.name, Colour (t.colour));
  183. return cs;
  184. }
  185. } // namespace juce