Version bump.
[geany-mirror.git] / tagmanager / r.c
blobc9be5132c4ebe1e3041fb46ac9b5b0f543088e4b
1 /*
2 * $Id$
4 * Copyright (c) 2003-2004, Ascher Stefan <stievie@utanet.at>
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 R language files.
10 * R is a programming language for statistical computing.
11 * R is GPL Software, get it from http://www.r-project.org/
15 * INCLUDE FILES
17 #include "general.h" /* must always come first */
19 #include <string.h>
20 #include <ctype.h> /* to define isalpha(), isalnum(), isspace() */
22 #include "entry.h"
23 #include "read.h"
24 #include "vstring.h"
26 /*#define R_REGEX*/
28 #define SKIPSPACE(ch) while (isspace((int)*ch)) \
29 ch++
31 #ifndef R_REGEX
32 static kindOption RKinds [] = {
33 { TRUE, 'f', "function", "functions" },
34 { TRUE, 's', "other", "libraries" }
36 #endif
38 #ifdef R_REGEX
39 static void installRRegex (const langType language)
41 /* This is a function, looks as follows:
42 * itent <- function(arg1, arg2) {
43 * do_something;
44 * }
46 addTagRegex (language,
47 "^[ \t]*([.a-zA-Z0-9_]+)([ \t]*)<-([ \t]*)function", "\\1", "f,function", NULL);
48 /* This loads someting, e.g. a library, simply: library(libname) */
49 addTagRegex (language,
50 "^[ \t]*(library|source|load|data)[\\(]([a-zA-Z0-9_]+)[\\)]", "\\2", "s,other", NULL);
52 #else
53 static void makeRTag(const vString* const name, int kind)
55 tagEntryInfo e;
56 initTagEntry(&e, vStringValue(name));
58 e.kindName = RKinds[kind].name;
59 e.kind = RKinds[kind].letter;
61 makeTagEntry(&e);
64 extern void createRTags(void)
66 vString *vLine = vStringNew();
67 vString *name = vStringNew();
68 int ikind;
69 const unsigned char *line;
71 while ((line = fileReadLine()) != NULL)
73 const unsigned char *cp = (const unsigned char*)line;
75 vStringClear(name);
76 while ((*cp != '\0') && (*cp != '#')) {
77 /* iterate to the end of line or to a comment */
78 ikind = -1;
79 switch (*cp) {
80 case 'l':
81 case 's':
82 if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
83 /* load a library: library(tools) */
84 cp += 7;
85 SKIPSPACE(cp);
86 if (*cp == '(')
87 ikind = 1;
88 else
89 cp -= 7;
90 } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
91 /* load a source file: source("myfile.r") */
92 cp += 6;
93 SKIPSPACE(cp);
94 if (*cp == '(')
95 ikind = 2;
96 else
97 cp -= 6;
99 if (ikind != -1) {
100 cp++;
102 vStringClear(name);
103 while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
104 vStringPut(name, (int)*cp);
105 cp++;
107 vStringTerminate(name);
109 /* if the string really exists, make a tag of it */
110 if (vStringLength(name) > 0)
111 makeRTag(name, ikind);
113 /* prepare for the next iteration */
114 vStringClear(name);
115 } else {
116 vStringPut(name, (int)*cp);
117 cp++;
119 break;
120 case '<':
121 cp++;
122 if (*cp == '-') {
123 /* assignment: ident <- someval */
124 cp++;
125 SKIPSPACE(cp);
127 if (*cp == '\0') {
128 /* not in this line, read next */
129 /* sometimes functions are declared this way:
130 ident <-
131 function(...)
135 I don't know if there is a reason to write the function keyword
136 in a new line
138 if ((line = fileReadLine()) != NULL) {
139 cp = (const unsigned char*)line;
140 SKIPSPACE(cp);
144 if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
145 /* it's a function: ident <- function(args) */
146 cp += 8;
147 vStringTerminate(name);
148 /* if the string really exists, make a tag of it */
149 if (vStringLength(name) > 0)
150 makeRTag(name, 0);
152 /* prepare for the next iteration */
153 vStringClear(name);
154 break;
157 case ' ':
158 case '\x009':
159 /* skip whitespace */
160 cp++;
161 break;
162 default:
163 /* collect all characters that could be a part of an identifier */
164 vStringPut(name, (int)*cp);
165 cp++;
166 break;
171 vStringDelete(name);
172 vStringDelete(vLine);
174 #endif
176 extern parserDefinition* RParser (void)
178 /* *.r: R files
179 * *.s;*.q: S files
181 static const char *const extensions [] = { "r", "s", "q", NULL };
182 parserDefinition* const def = parserNew ("R");
183 #ifndef R_REGEX
184 def->kinds = RKinds;
185 def->kindCount = 4;
186 #endif
187 def->extensions = extensions;
188 #ifndef R_REGEX
189 def->parser = createRTags;
190 #else
191 def->initialize = installRRegex;
192 def->regex = TRUE;
193 #endif
194 return def;
197 /* vi:set tabstop=8 shiftwidth=4: */