scanner.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "tree_sitter/parser.h"
  2. #include <wctype.h>
  3. enum TokenType {
  4. TEMPLATE_CHARS_SINGLE,
  5. TEMPLATE_CHARS_DOUBLE,
  6. TEMPLATE_CHARS_SINGLE_SINGLE,
  7. TEMPLATE_CHARS_DOUBLE_SINGLE,
  8. TEMPLATE_CHARS_RAW_SLASH,
  9. BLOCK_COMMENT,
  10. DOCUMENTATION_BLOCK_COMMENT,
  11. };
  12. void *tree_sitter_dart_external_scanner_create() { return NULL; }
  13. void tree_sitter_dart_external_scanner_destroy(void *p) {}
  14. void tree_sitter_dart_external_scanner_reset(void *p) {}
  15. unsigned tree_sitter_dart_external_scanner_serialize(void *p, char *buffer) { return 0; }
  16. void tree_sitter_dart_external_scanner_deserialize(void *p, const char *b, unsigned n) {}
  17. static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
  18. static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
  19. static bool scan_multiline_comments(TSLexer *lexer) {
  20. bool documentation_comment = false;
  21. advance(lexer);
  22. if (lexer->lookahead != '*') return false;
  23. advance(lexer);
  24. if (lexer->lookahead == '*') documentation_comment = true;
  25. bool after_star = false;
  26. unsigned nesting_depth = 1;
  27. for (;;) {
  28. switch (lexer->lookahead) {
  29. case '\0':
  30. return false;
  31. case '*':
  32. advance(lexer);
  33. after_star = true;
  34. break;
  35. case '/':
  36. if (after_star) {
  37. advance(lexer);
  38. after_star = false;
  39. nesting_depth--;
  40. if (nesting_depth == 0) {
  41. if (!documentation_comment) {
  42. lexer->result_symbol = BLOCK_COMMENT;
  43. } else {
  44. lexer->result_symbol = DOCUMENTATION_BLOCK_COMMENT;
  45. }
  46. return true;
  47. }
  48. } else {
  49. advance(lexer);
  50. after_star = false;
  51. if (lexer->lookahead == '*') {
  52. nesting_depth++;
  53. advance(lexer);
  54. }
  55. }
  56. break;
  57. default:
  58. advance(lexer);
  59. after_star = false;
  60. break;
  61. }
  62. }
  63. return false;
  64. }
  65. static bool scan_templates(TSLexer *lexer, const bool *valid_symbols) {
  66. if(valid_symbols[TEMPLATE_CHARS_DOUBLE]) {
  67. lexer->result_symbol = TEMPLATE_CHARS_DOUBLE;
  68. } else if (valid_symbols[TEMPLATE_CHARS_SINGLE]) {
  69. lexer->result_symbol = TEMPLATE_CHARS_SINGLE;
  70. } else if (valid_symbols[TEMPLATE_CHARS_SINGLE_SINGLE]) {
  71. lexer->result_symbol = TEMPLATE_CHARS_SINGLE_SINGLE;
  72. } else {
  73. lexer->result_symbol = TEMPLATE_CHARS_DOUBLE_SINGLE;
  74. }
  75. for (bool has_content = false;; has_content = true) {
  76. lexer->mark_end(lexer);
  77. switch (lexer->lookahead) {
  78. case '\'':
  79. case '"':
  80. return has_content;
  81. case '\n':
  82. if (valid_symbols[TEMPLATE_CHARS_DOUBLE_SINGLE] || valid_symbols[TEMPLATE_CHARS_SINGLE_SINGLE]) return false;
  83. advance(lexer);
  84. break;
  85. case '\0':
  86. return false;
  87. case '$':
  88. return has_content;
  89. case '\\':
  90. if (valid_symbols[TEMPLATE_CHARS_RAW_SLASH]) {
  91. lexer->result_symbol = TEMPLATE_CHARS_RAW_SLASH;
  92. advance(lexer);
  93. } else {
  94. return has_content;
  95. }
  96. break;
  97. default:
  98. advance(lexer);
  99. }
  100. }
  101. return true;
  102. }
  103. bool tree_sitter_dart_external_scanner_scan(void *payload, TSLexer *lexer,
  104. const bool *valid_symbols) {
  105. if (
  106. valid_symbols[TEMPLATE_CHARS_DOUBLE] ||
  107. valid_symbols[TEMPLATE_CHARS_SINGLE] ||
  108. valid_symbols[TEMPLATE_CHARS_DOUBLE_SINGLE] ||
  109. valid_symbols[TEMPLATE_CHARS_SINGLE_SINGLE]
  110. ) {
  111. return scan_templates(lexer, valid_symbols);
  112. }
  113. while (iswspace(lexer->lookahead)) lexer->advance(lexer, true);
  114. if (lexer->lookahead == '/') {
  115. return scan_multiline_comments(lexer);
  116. }
  117. return false;
  118. }