Remove duplicate NEWS item
[geany-mirror.git] / tagmanager / r.c
blobc1aac5e88cecadfbe3076f5cbba397814114363b
1 /*
2 * Copyright (c) 2003-2004, Ascher Stefan <stievie@utanet.at>
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License.
7 * This module contains functions for generating tags for R language files.
8 * R is a programming language for statistical computing.
9 * R is GPL Software, get it from http://www.r-project.org/
13 * INCLUDE FILES
15 #include "general.h" /* must always come first */
17 #include <string.h>
18 #include <ctype.h> /* to define isalpha(), isalnum(), isspace() */
20 #include "entry.h"
21 #include "read.h"
22 #include "vstring.h"
24 /*#define R_REGEX*/
26 #define SKIPSPACE(ch) while (isspace((int)*ch)) \
27 ch++
29 #ifndef R_REGEX
30 static kindOption RKinds [] = {
31 { TRUE, 'f', "function", "functions" },
32 { TRUE, 's', "other", "libraries" }
34 #endif
36 #ifdef R_REGEX
37 static void installRRegex (const langType language)
39 /* This is a function, looks as follows:
40 * itent <- function(arg1, arg2) {
41 * do_something;
42 * }
44 addTagRegex (language,
45 "^[ \t]*([.a-zA-Z0-9_]+)([ \t]*)<-([ \t]*)function", "\\1", "f,function", NULL);
46 /* This loads someting, e.g. a library, simply: library(libname) */
47 addTagRegex (language,
48 "^[ \t]*(library|source|load|data)[\\(]([a-zA-Z0-9_]+)[\\)]", "\\2", "s,other", NULL);
50 #else
51 static void makeRTag(const vString* const name, int kind)
53 tagEntryInfo e;
54 initTagEntry(&e, vStringValue(name));
56 e.kindName = RKinds[kind].name;
57 e.kind = RKinds[kind].letter;
59 makeTagEntry(&e);
62 extern void createRTags(void)
64 vString *vLine = vStringNew();
65 vString *name = vStringNew();
66 int ikind;
67 const unsigned char *line;
69 while ((line = fileReadLine()) != NULL)
71 const unsigned char *cp = (const unsigned char*)line;
73 vStringClear(name);
74 while ((*cp != '\0') && (*cp != '#')) {
75 /* iterate to the end of line or to a comment */
76 ikind = -1;
77 switch (*cp) {
78 case 'l':
79 case 's':
80 if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
81 /* load a library: library(tools) */
82 cp += 7;
83 SKIPSPACE(cp);
84 if (*cp == '(')
85 ikind = 1;
86 else
87 cp -= 7;
88 } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
89 /* load a source file: source("myfile.r") */
90 cp += 6;
91 SKIPSPACE(cp);
92 if (*cp == '(')
93 ikind = 2;
94 else
95 cp -= 6;
97 if (ikind != -1) {
98 cp++;
100 vStringClear(name);
101 while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
102 vStringPut(name, (int)*cp);
103 cp++;
105 vStringTerminate(name);
107 /* if the string really exists, make a tag of it */
108 if (vStringLength(name) > 0)
109 makeRTag(name, ikind);
111 /* prepare for the next iteration */
112 vStringClear(name);
113 } else {
114 vStringPut(name, (int)*cp);
115 cp++;
117 break;
118 case '<':
119 cp++;
120 if (*cp == '-') {
121 /* assignment: ident <- someval */
122 cp++;
123 SKIPSPACE(cp);
125 if (*cp == '\0') {
126 /* not in this line, read next */
127 /* sometimes functions are declared this way:
128 ident <-
129 function(...)
133 I don't know if there is a reason to write the function keyword
134 in a new line
136 if ((line = fileReadLine()) != NULL) {
137 cp = (const unsigned char*)line;
138 SKIPSPACE(cp);
142 if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
143 /* it's a function: ident <- function(args) */
144 cp += 8;
145 vStringTerminate(name);
146 /* if the string really exists, make a tag of it */
147 if (vStringLength(name) > 0)
148 makeRTag(name, 0);
150 /* prepare for the next iteration */
151 vStringClear(name);
152 break;
155 case ' ':
156 case '\x009':
157 /* skip whitespace */
158 cp++;
159 break;
160 default:
161 /* collect all characters that could be a part of an identifier */
162 vStringPut(name, (int)*cp);
163 cp++;
164 break;
169 vStringDelete(name);
170 vStringDelete(vLine);
172 #endif
174 extern parserDefinition* RParser (void)
176 /* *.r: R files
177 * *.s;*.q: S files
179 static const char *const extensions [] = { "r", "s", "q", NULL };
180 parserDefinition* const def = parserNew ("R");
181 #ifndef R_REGEX
182 def->kinds = RKinds;
183 def->kindCount = 4;
184 #endif
185 def->extensions = extensions;
186 #ifndef R_REGEX
187 def->parser = createRTags;
188 #else
189 def->initialize = installRRegex;
190 def->regex = TRUE;
191 #endif
192 return def;
195 /* vi:set tabstop=8 shiftwidth=4: */