4 * Copyright (c) 2000-2003, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for generating tags for Python language
15 #include "general.h" /* must always come first */
29 K_CLASS
, K_FUNCTION
, K_MEMBER
32 static kindOption PythonKinds
[] = {
33 {TRUE
, 'c', "class", "classes"},
34 {TRUE
, 'f', "function", "functions"},
35 {TRUE
, 'm', "member", "class members"}
39 * FUNCTION DEFINITIONS
41 /* tagEntryInfo and vString should be preinitialized/preallocated but not
42 * necessary. If successful you will find class name in vString
45 static boolean
isIdentifierFirstCharacter (int c
)
47 return (boolean
) (isalpha (c
) || c
== '_');
50 static boolean
isIdentifierCharacter (int c
)
52 return (boolean
) (isalnum (c
) || c
== '_');
55 static void makeFunctionTag (vString
*const function
, vString
*const class)
58 initTagEntry (&tag
, vStringValue (function
));
59 if (vStringLength (class) > 0)
61 tag
.kindName
= "member";
63 tag
.extensionFields
.scope
[0] = "class";
64 tag
.extensionFields
.scope
[1] = vStringValue (class);
68 tag
.kindName
= "function";
71 if (strncmp (vStringValue (function
), "__", 2) == 0 &&
72 strcmp (vStringValue (function
), "__init__") != 0)
74 tag
.extensionFields
.access
= "private";
75 tag
.isFileScope
= TRUE
;
79 tag
.extensionFields
.access
= "public";
82 if (vStringLength (class) > 0 && Option
.include
.qualifiedTags
)
84 vString
*tagname
= vStringNew ();
85 vStringCat (tagname
, class);
86 vStringPut (tagname
, '.');
87 vStringCat (tagname
, function
);
88 tag
.name
= vStringValue (tagname
);
90 vStringDelete (tagname
);
94 static void makeClassTag (vString
*const class, vString
*const inheritance
)
97 initTagEntry (&tag
, vStringValue (class));
98 tag
.kindName
= "class";
100 tag
.extensionFields
.inheritance
= vStringValue (inheritance
);
104 static const unsigned char *skipSpace (const unsigned char *cp
)
106 while (isspace ((int) *cp
))
111 static const unsigned char *parseIdentifier (
112 const unsigned char *cp
, vString
*const identifier
)
114 vStringClear (identifier
);
115 while (isIdentifierCharacter ((int) *cp
))
117 vStringPut (identifier
, (int) *cp
);
120 vStringTerminate (identifier
);
124 static void parseClass (const unsigned char *cp
, vString
*const class)
126 vString
*const inheritance
= vStringNew ();
127 vStringClear (inheritance
);
128 cp
= parseIdentifier (cp
, class);
133 while (*cp
!= ')' && *cp
!= '\0')
135 vStringPut (inheritance
, *cp
);
138 vStringTerminate (inheritance
);
140 makeClassTag (class, inheritance
);
141 vStringDelete (inheritance
);
144 static void parseFunction (const unsigned char *cp
, vString
*const class)
146 vString
*const identifier
= vStringNew ();
147 cp
= parseIdentifier (cp
, identifier
);
148 makeFunctionTag (identifier
, class);
149 vStringDelete (identifier
);
152 static void findPythonTags (void)
154 vString
*const class = vStringNew ();
155 vString
*const identifier
= vStringNew ();
156 const unsigned char *line
;
157 int class_indent
= 0;
158 boolean longStringLiteral
= FALSE
;
160 while ((line
= fileReadLine ()) != NULL
)
162 const unsigned char *cp
= line
;
168 if (*cp
== '#' || *cp
== '\0') /* skip comment or blank line */
171 if (longStringLiteral
)
173 cp
= (const unsigned char*) strstr ((const char*) cp
, "\"\"\"");
178 longStringLiteral
= FALSE
;
182 if (isIdentifierFirstCharacter ((int) *cp
))
184 if (indent
<= class_indent
)
185 vStringClear (class);
187 cp
= parseIdentifier (cp
, identifier
);
188 if (isspace ((int) *cp
))
191 if (strcmp (vStringValue (identifier
), "def") == 0)
192 parseFunction (cp
, class);
193 else if (strcmp (vStringValue (identifier
), "class") == 0)
195 parseClass (cp
, class);
196 class_indent
= indent
;
200 if ((cp
= (const unsigned char*) strstr ((const char*)cp
, "\"\"\"")) != NULL
)
203 cp
= (const unsigned char*) strstr ((const char*) cp
, "\"\"\"");
205 longStringLiteral
= TRUE
;
208 vStringDelete (identifier
);
209 vStringDelete (class);
212 extern parserDefinition
*PythonParser (void)
214 static const char *const extensions
[] = { "py", "python", NULL
};
215 parserDefinition
*def
= parserNew ("Python");
216 def
->kinds
= PythonKinds
;
217 def
->kindCount
= KIND_COUNT (PythonKinds
);
218 def
->extensions
= extensions
;
219 def
->parser
= findPythonTags
;
223 /* vi:set tabstop=4 shiftwidth=4: */