Make parser includes closer to uctags and sync parser license header
[geany-mirror.git] / ctags / parsers / r.c
blobc2279a4dd6a6677b99b6b186d279ac758580f1cb
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 version 2 or (at your option) any later version.
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 "debug.h"
21 #include "entry.h"
22 #include "read.h"
23 #include "vstring.h"
25 /*#define R_REGEX*/
27 #define SKIPSPACE(ch) while (isspace((int)*ch)) \
28 ch++
30 #ifndef R_REGEX
31 typedef enum {
32 K_FUNCTION,
33 K_LIBRARY,
34 K_SOURCE,
35 KIND_COUNT
36 } rKind;
38 static kindOption RKinds [KIND_COUNT] = {
39 { TRUE, 'f', "function", "functions" },
40 { TRUE, 'l', "library", "libraries" },
41 { TRUE, 's', "source", "sources" },
43 #endif
45 #ifdef R_REGEX
46 static void installRRegex (const langType language)
48 /* This is a function, looks as follows:
49 * itent <- function(arg1, arg2) {
50 * do_something;
51 * }
53 addTagRegex (language,
54 "^[ \t]*([.a-zA-Z0-9_]+)([ \t]*)<-([ \t]*)function", "\\1", "f,function", NULL);
55 /* This loads someting, e.g. a library, simply: library(libname) */
56 addTagRegex (language,
57 "^[ \t]*(library|source|load|data)[\\(]([a-zA-Z0-9_]+)[\\)]", "\\2", "s,other", NULL);
59 #else
60 static void makeRTag(const vString* const name, rKind kind)
62 tagEntryInfo e;
63 initTagEntry(&e, vStringValue(name));
65 Assert(kind < KIND_COUNT);
67 e.kindName = RKinds[kind].name;
68 e.kind = RKinds[kind].letter;
70 makeTagEntry(&e);
73 static void createRTags(void)
75 vString *vLine = vStringNew();
76 vString *name = vStringNew();
77 int ikind;
78 const unsigned char *line;
80 while ((line = fileReadLine()) != NULL)
82 const unsigned char *cp = (const unsigned char*)line;
84 vStringClear(name);
85 while ((*cp != '\0') && (*cp != '#')) {
86 /* iterate to the end of line or to a comment */
87 ikind = -1;
88 switch (*cp) {
89 case 'l':
90 case 's':
91 if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
92 /* load a library: library(tools) */
93 cp += 7;
94 SKIPSPACE(cp);
95 if (*cp == '(')
96 ikind = K_LIBRARY;
97 else
98 cp -= 7;
99 } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
100 /* load a source file: source("myfile.r") */
101 cp += 6;
102 SKIPSPACE(cp);
103 if (*cp == '(')
104 ikind = K_SOURCE;
105 else
106 cp -= 6;
108 if (ikind != -1) {
109 cp++;
111 vStringClear(name);
112 while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
113 vStringPut(name, (int)*cp);
114 cp++;
116 vStringTerminate(name);
118 /* if the string really exists, make a tag of it */
119 if (vStringLength(name) > 0)
120 makeRTag(name, ikind);
122 /* prepare for the next iteration */
123 vStringClear(name);
124 } else {
125 vStringPut(name, (int)*cp);
126 cp++;
128 break;
129 case '<':
130 cp++;
131 if (*cp == '-') {
132 /* assignment: ident <- someval */
133 cp++;
134 SKIPSPACE(cp);
136 if (*cp == '\0') {
137 /* not in this line, read next */
138 /* sometimes functions are declared this way:
139 ident <-
140 function(...)
144 I don't know if there is a reason to write the function keyword
145 in a new line
147 if ((line = fileReadLine()) != NULL) {
148 cp = (const unsigned char*)line;
149 SKIPSPACE(cp);
153 if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
154 /* it's a function: ident <- function(args) */
155 cp += 8;
156 vStringTerminate(name);
157 /* if the string really exists, make a tag of it */
158 if (vStringLength(name) > 0)
159 makeRTag(name, K_FUNCTION);
161 /* prepare for the next iteration */
162 vStringClear(name);
163 break;
166 case ' ':
167 case '\x009':
168 /* skip whitespace */
169 cp++;
170 break;
171 default:
172 /* collect all characters that could be a part of an identifier */
173 vStringPut(name, (int)*cp);
174 cp++;
175 break;
180 vStringDelete(name);
181 vStringDelete(vLine);
183 #endif
185 extern parserDefinition* RParser (void)
187 /* *.r: R files
188 * *.s;*.q: S files
190 static const char *const extensions [] = { "r", "s", "q", NULL };
191 parserDefinition* const def = parserNew ("R");
192 #ifndef R_REGEX
193 def->kinds = RKinds;
194 def->kindCount = KIND_COUNT (RKinds);
195 #endif
196 def->extensions = extensions;
197 #ifndef R_REGEX
198 def->parser = createRTags;
199 #else
200 def->initialize = installRRegex;
201 def->regex = TRUE;
202 #endif
203 return def;
206 /* vi:set tabstop=8 shiftwidth=4: */