Making "inline" behave like an attribute. Fixes #1
[arduino-ctags.git] / sml.c
blob9fbb21b5b015e0008e4311cf457d094cabc6d682
1 /*
2 * $Id: sml.c 536 2007-06-02 06:09:00Z elliotth $
4 * Copyright (c) 2002, Venkatesh Prasad Ranganath and 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 SML language files.
13 * INCLUDE FILES
15 #include "general.h" /* must always come first */
17 #include <string.h>
19 #include "entry.h"
20 #include "parse.h"
21 #include "read.h"
22 #include "vstring.h"
25 * DATA DECLARATIONS
27 typedef enum {
28 K_AND = -2,
29 K_NONE = -1,
30 K_EXCEPTION,
31 K_FUNCTION,
32 K_FUNCTOR,
33 K_SIGNATURE,
34 K_STRUCTURE,
35 K_TYPE,
36 K_VAL
37 } smlKind;
40 * DATA DEFINITIONS
42 static kindOption SmlKinds[] = {
43 { TRUE, 'e', "exception", "exception declarations" },
44 { TRUE, 'f', "function", "function definitions" },
45 { TRUE, 'c', "functor", "functor definitions" },
46 { TRUE, 's', "signature", "signature declarations" },
47 { TRUE, 'r', "structure", "structure declarations" },
48 { TRUE, 't', "type", "type definitions" },
49 { TRUE, 'v', "value", "value bindings" }
52 static struct {
53 const char *keyword;
54 smlKind kind;
55 } SmlKeywordTypes [] = {
56 { "abstype", K_TYPE },
57 { "and", K_AND },
58 { "datatype", K_TYPE },
59 { "exception", K_EXCEPTION },
60 { "functor", K_FUNCTOR },
61 { "fun", K_FUNCTION },
62 { "signature", K_SIGNATURE },
63 { "structure", K_STRUCTURE },
64 { "type", K_TYPE },
65 { "val", K_VAL }
68 static unsigned int CommentLevel = 0;
71 * FUNCTION DEFINITIONS
74 static void makeSmlTag (smlKind type, vString *name)
76 tagEntryInfo tag;
77 initTagEntry (&tag, vStringValue (name));
78 tag.kindName = SmlKinds [type].name;
79 tag.kind = SmlKinds [type].letter;
80 makeTagEntry (&tag);
83 static const unsigned char *skipSpace (const unsigned char *cp)
85 while (isspace ((int) *cp))
86 ++cp;
87 return cp;
90 static boolean isIdentifier (int c)
92 boolean result = FALSE;
93 /* Consider '_' as an delimiter to aid user in tracking it's usage. */
94 const char *const alternateIdentifiers = "!%&$#+-<>=/?@\\~'^|*_";
95 if (isalnum (c))
96 result = TRUE;
97 else if (c != '\0' && strchr (alternateIdentifiers, c) != NULL)
98 result = TRUE;
99 return result;
102 static const unsigned char *parseIdentifier (
103 const unsigned char *cp, vString *const identifier)
105 boolean stringLit = FALSE;
106 vStringClear (identifier);
107 while (*cp != '\0' && (!isIdentifier ((int) *cp) || stringLit))
109 int oneback = *cp;
110 cp++;
111 if (oneback == '(' && *cp == '*' && stringLit == FALSE)
113 CommentLevel++;
114 return ++cp;
116 if (*cp == '"' && oneback != '\\')
118 stringLit = TRUE;
119 continue;
121 if (stringLit && *cp == '"' && oneback != '\\')
122 stringLit = FALSE;
124 if (strcmp ((const char *) cp, "") == 0 || cp == NULL)
125 return cp;
127 while (isIdentifier ((int) *cp))
129 vStringPut (identifier, (int) *cp);
130 cp++;
132 vStringTerminate (identifier);
133 return cp;
136 static smlKind findNextIdentifier (const unsigned char **cp)
138 smlKind result = K_NONE;
139 vString *const identifier = vStringNew ();
140 unsigned int count = sizeof (SmlKeywordTypes) / sizeof (SmlKeywordTypes [0]);
141 unsigned int i;
142 *cp = parseIdentifier (*cp, identifier);
143 for (i = 0 ; i < count && result == K_NONE ; ++i)
145 const char *id = vStringValue (identifier);
146 if (strcmp (id, SmlKeywordTypes [i].keyword) == 0)
147 result = SmlKeywordTypes [i].kind;
149 vStringDelete (identifier);
150 return result;
153 static void findSmlTags (void)
155 vString *const identifier = vStringNew ();
156 const unsigned char *line;
157 smlKind lastTag = K_NONE;
159 while ((line = fileReadLine ()) != NULL)
161 const unsigned char *cp = skipSpace (line);
164 smlKind foundTag;
165 if (CommentLevel != 0)
167 cp = (const unsigned char *) strstr ((const char *) cp, "*)");
168 if (cp == NULL)
169 continue;
170 else
172 --CommentLevel;
173 cp += 2;
176 foundTag = findNextIdentifier (&cp);
177 if (foundTag != K_NONE)
179 cp = skipSpace (cp);
180 cp = parseIdentifier (cp, identifier);
181 if (foundTag == K_AND)
182 makeSmlTag (lastTag, identifier);
183 else
185 makeSmlTag (foundTag, identifier);
186 lastTag = foundTag;
189 if (strstr ((const char *) cp, "(*") != NULL)
191 cp += 2;
192 cp = (const unsigned char *) strstr ((const char *) cp, "*)");
193 if (cp == NULL)
194 ++CommentLevel;
196 } while (cp != NULL && strcmp ((const char *) cp, "") != 0);
198 vStringDelete (identifier);
201 extern parserDefinition *SmlParser (void)
203 static const char *const extensions[] = { "sml", "sig", NULL };
204 parserDefinition *def = parserNew ("SML");
205 def->kinds = SmlKinds;
206 def->kindCount = KIND_COUNT (SmlKinds);
207 def->extensions = extensions;
208 def->parser = findSmlTags;
209 return def;
212 /* vi:set tabstop=4 shiftwidth=4: */