2525#include "read.h"
2626#include "routines.h"
2727#include "strlist.h"
28+ #include "subparser.h"
2829#include "vstring.h"
2930
31+ #include "ruby.h"
32+
3033/*
3134* DATA DECLARATIONS
3235*/
@@ -82,6 +85,8 @@ static fieldDefinition RubyFields[] = {
8285
8386struct blockData {
8487 stringList * mixin ;
88+ rubySubparser * subparser ;
89+ int subparserCorkIndex ;
8590};
8691
8792static NestingLevels * nesting = NULL ;
@@ -205,7 +210,8 @@ static bool advanceWhile (const unsigned char** s, bool (*predicate) (int))
205210 return * s != original_pos ;
206211}
207212
208- static bool canMatchKeyword (const unsigned char * * s , const char * literal )
213+ #define canMatchKeyword rubyCanMatchKeyword
214+ extern bool rubyCanMatchKeyword (const unsigned char * * s , const char * literal )
209215{
210216 return canMatch (s , literal , notIdentChar );
211217}
@@ -214,7 +220,8 @@ static bool canMatchKeyword (const unsigned char** s, const char* literal)
214220 * Extends canMatch. Works similarly, but allows assignment to precede
215221 * the keyword, as block assignment is a common Ruby idiom.
216222 */
217- static bool canMatchKeywordWithAssign (const unsigned char * * s , const char * literal )
223+ #define canMatchKeywordWithAssign rubyCanMatchKeywordWithAssign
224+ extern bool rubyCanMatchKeywordWithAssign (const unsigned char * * s , const char * literal )
218225{
219226 const unsigned char * original_pos = * s ;
220227
@@ -360,7 +367,8 @@ static bool charIsIn (char ch, const char* list)
360367}
361368
362369/* Advances 'cp' over leading whitespace. */
363- static void skipWhitespace (const unsigned char * * cp )
370+ #define skipWhitespace rubySkipWhitespace
371+ extern void rubySkipWhitespace (const unsigned char * * cp )
364372{
365373 while (isspace (* * cp ))
366374 {
@@ -452,6 +460,16 @@ static rubyKind parseIdentifier (
452460 return kind ;
453461}
454462
463+ extern bool rubyParseMethodName (const unsigned char * * cp , vString * vstr )
464+ {
465+ return (parseIdentifier (cp , vstr , K_METHOD ) == K_METHOD );
466+ }
467+
468+ extern bool rubyParseModuleName (const unsigned char * * cp , vString * vstr )
469+ {
470+ return (parseIdentifier (cp , vstr , K_MODULE ) == K_MODULE );
471+ }
472+
455473static void parseString (const unsigned char * * cp , unsigned char boundary , vString * vstr )
456474{
457475 while (* * cp != 0 && * * cp != boundary )
@@ -466,6 +484,13 @@ static void parseString (const unsigned char** cp, unsigned char boundary, vStri
466484 ++ * cp ;
467485}
468486
487+ extern bool rubyParseString (const unsigned char * * cp , unsigned char boundary , vString * vstr )
488+ {
489+ const unsigned char * p = * cp ;
490+ parseString (cp , boundary , vstr );
491+ return (p != * cp );
492+ }
493+
469494static void parseSignature (const unsigned char * * cp , vString * vstr )
470495{
471496 int depth = 1 ;
@@ -646,6 +671,17 @@ static void enterUnnamedScope (void)
646671 nestingLevelsPush (nesting , r );
647672}
648673
674+ static void parasiteToScope (rubySubparser * subparser , int subparserCorkIndex )
675+ {
676+ NestingLevel * nl = nestingLevelsGetCurrent (nesting );
677+ struct blockData * bdata = nestingLevelGetUserData (nl );
678+ bdata -> subparser = subparser ;
679+ bdata -> subparserCorkIndex = subparserCorkIndex ;
680+
681+ if (subparser -> enterBlockNotify )
682+ subparser -> enterBlockNotify (subparser , subparserCorkIndex );
683+ }
684+
649685static void attachMixinField (int corkIndex , stringList * mixinSpec )
650686{
651687 vString * mixinField = stringListItem (mixinSpec , 0 );
@@ -672,6 +708,16 @@ static void deleteBlockData (NestingLevel *nl)
672708 if (e && !e -> placeholder )
673709 e -> extensionFields .endLine = getInputLineNumber ();
674710
711+ tagEntryInfo * sub_e ;
712+ if (bdata -> subparserCorkIndex != CORK_NIL
713+ && (sub_e = getEntryInCorkQueue (bdata -> subparserCorkIndex )))
714+ {
715+ sub_e -> extensionFields .endLine = getInputLineNumber ();
716+ if (bdata -> subparser )
717+ bdata -> subparser -> leaveBlockNotify (bdata -> subparser ,
718+ bdata -> subparserCorkIndex );
719+ }
720+
675721 if (bdata -> mixin )
676722 stringListDelete (bdata -> mixin );
677723}
@@ -862,6 +908,33 @@ static int readAndEmitDef (const unsigned char **cp)
862908 return corkIndex ;
863909}
864910
911+ static rubySubparser * notifyLine (const unsigned char * * cp )
912+ {
913+ subparser * sub ;
914+ rubySubparser * rubysub = NULL ;
915+
916+ foreachSubparser (sub , false)
917+ {
918+ rubysub = (rubySubparser * )sub ;
919+ rubysub -> corkIndex = CORK_NIL ;
920+
921+ if (rubysub -> lineNotify )
922+ {
923+ enterSubparser (sub );
924+ const unsigned char * base = * cp ;
925+ rubysub -> corkIndex = rubysub -> lineNotify (rubysub , cp );
926+ leaveSubparser ();
927+ if (rubysub -> corkIndex != CORK_NIL )
928+ break ;
929+ * cp = base ;
930+ }
931+ }
932+
933+ if (rubysub && rubysub -> corkIndex != CORK_NIL )
934+ return rubysub ;
935+ return NULL ;
936+ }
937+
865938static void findRubyTags (void )
866939{
867940 const unsigned char * line ;
@@ -882,6 +955,7 @@ static void findRubyTags (void)
882955 */
883956 while ((line = readLineFromInputFile ()) != NULL )
884957 {
958+ rubySubparser * subparser = CORK_NIL ;
885959 const unsigned char * cp = line ;
886960 /* if we expect a separator after a while, for, or until statement
887961 * separators are "do", ";" or newline */
@@ -1028,6 +1102,8 @@ static void findRubyTags (void)
10281102 /* TODO: store the method for controlling visibility
10291103 * to the "access:" field of the tag.*/
10301104 }
1105+ else
1106+ subparser = notifyLine (& cp );
10311107
10321108
10331109 while (* cp != '\0' )
@@ -1057,7 +1133,11 @@ static void findRubyTags (void)
10571133 else if (canMatchKeyword (& cp , "do" ))
10581134 {
10591135 if (! expect_separator )
1136+ {
10601137 enterUnnamedScope ();
1138+ if (subparser && subparser -> corkIndex )
1139+ parasiteToScope (subparser , subparser -> corkIndex );
1140+ }
10611141 else
10621142 expect_separator = false;
10631143 }
0 commit comments