manual: added documentation about replacement of 'untitled.ext' with filename (#1804)
[geany-mirror.git] / ctags / parsers / r.c
blob6723fd955084f41dc733f953451b543cf137c0df
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"
24 #include "routines.h"
27 #define SKIPSPACE(ch) while (isspace((int)*ch)) \
28 ch++
30 typedef enum {
31 K_FUNCTION,
32 K_LIBRARY,
33 K_SOURCE,
34 KIND_COUNT
35 } rKind;
37 static kindOption RKinds [KIND_COUNT] = {
38 {true, 'f', "function", "functions"},
39 {true, 'l', "library", "libraries"},
40 {true, 's', "source", "sources"},
43 static void makeRTag (const vString * const name, rKind kind)
45 tagEntryInfo e;
46 initTagEntry(&e, vStringValue(name), &(RKinds[kind]));
48 Assert (kind < KIND_COUNT);
50 makeTagEntry (&e);
53 static void createRTags (void)
55 vString *vLine = vStringNew ();
56 vString *name = vStringNew ();
57 int ikind;
58 const unsigned char *line;
60 while ((line = readLineFromInputFile ()) != NULL)
62 const unsigned char *cp = (const unsigned char *) line;
64 vStringClear (name);
65 while ((*cp != '\0') && (*cp != '#'))
67 /* iterate to the end of line or to a comment */
68 ikind = -1;
69 switch (*cp) {
70 case 'l':
71 case 's':
72 if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
73 /* load a library: library(tools) */
74 cp += 7;
75 SKIPSPACE(cp);
76 if (*cp == '(')
77 ikind = K_LIBRARY;
78 else
79 cp -= 7;
80 } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
81 /* load a source file: source("myfile.r") */
82 cp += 6;
83 SKIPSPACE(cp);
84 if (*cp == '(')
85 ikind = K_SOURCE;
86 else
87 cp -= 6;
89 if (ikind != -1) {
90 cp++;
92 vStringClear(name);
93 while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
94 vStringPut(name, (int)*cp);
95 cp++;
98 /* if the string really exists, make a tag of it */
99 if (vStringLength(name) > 0)
100 makeRTag(name, ikind);
102 /* prepare for the next iteration */
103 vStringClear(name);
104 } else {
105 vStringPut(name, (int)*cp);
106 cp++;
108 break;
109 case '<':
110 cp++;
111 if (*cp == '-') {
112 /* assignment: ident <- someval */
113 cp++;
114 SKIPSPACE(cp);
116 if (*cp == '\0') {
117 /* not in this line, read next */
118 /* sometimes functions are declared this way:
119 ident <-
120 function(...)
124 I don't know if there is a reason to write the function keyword
125 in a new line
127 if ((line = readLineFromInputFile()) != NULL) {
128 cp = (const unsigned char*)line;
129 SKIPSPACE(cp);
133 if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
134 /* it's a function: ident <- function(args) */
135 cp += 8;
136 /* if the string really exists, make a tag of it */
137 if (vStringLength(name) > 0)
138 makeRTag(name, K_FUNCTION);
140 /* prepare for the next iteration */
141 vStringClear(name);
142 break;
145 /* fall through */
146 case ' ':
147 case '\x009':
148 /* skip whitespace */
149 cp++;
150 break;
151 default:
152 /* collect all characters that could be a part of an identifier */
153 vStringPut(name, (int)*cp);
154 cp++;
155 break;
160 vStringDelete (name);
161 vStringDelete (vLine);
164 extern parserDefinition *RParser (void)
166 /* *.r: R files
167 * *.s;*.q: S files
169 static const char *const extensions [] = { "r", "s", "q", NULL };
170 parserDefinition *const def = parserNew ("R");
171 def->kinds = RKinds;
172 def->kindCount = ARRAY_SIZE (RKinds);
173 def->extensions = extensions;
174 def->parser = createRTags;
175 return def;