Merge pull request #41 from blackducksw/ubuntu_14
[ohcount] / src / parsers / d.rl
1 // d.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_D_PARSER_H
5 #define OHCOUNT_D_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *D_LANG = LANG_DMD;
11
12 // the languages entities
13 const char *d_entities[] = {
14   "space", "comment", "string", "any"
15 };
16
17 // constants associated with the entities
18 enum {
19   D_SPACE = 0, D_COMMENT, D_STRING, D_ANY
20 };
21
22 /*****************************************************************************/
23
24 %%{
25   machine d;
26   write data;
27   include common "common.rl";
28
29   # Line counting machine
30
31   action d_ccallback {
32     switch(entity) {
33     case D_SPACE:
34       ls
35       break;
36     case D_ANY:
37       code
38       break;
39     case INTERNAL_NL:
40       std_internal_newline(D_LANG)
41       break;
42     case NEWLINE:
43       std_newline(D_LANG)
44     }
45   }
46
47   action d_comment_nc_res { nest_count = 0; }
48   action d_comment_nc_inc { nest_count++; }
49   action d_comment_nc_dec { nest_count--; }
50
51   d_line_comment =
52     '//' @comment (
53       escaped_newline %{ entity = INTERNAL_NL; } %d_ccallback
54       |
55       ws
56       |
57       (nonnewline - ws) @comment
58     )*;
59   d_block_comment =
60     '/*' @comment (
61       newline %{ entity = INTERNAL_NL; } %d_ccallback
62       |
63       ws
64       |
65       (nonnewline - ws) @comment
66     )* :>> '*/';
67   d_nested_comment =
68     '/+' >d_comment_nc_res @comment (
69       newline %{ entity = INTERNAL_NL; } %d_ccallback
70       |
71       ws
72       |
73       '/+' @d_comment_nc_inc @comment
74       |
75       '+/' @d_comment_nc_dec @comment
76       |
77       ^space @comment
78     )* :>> ('+/' when { nest_count == 0 }) @comment;
79   d_comment = d_line_comment | d_block_comment | d_nested_comment;
80
81   d_sq_str =
82     '\'' @code (
83       escaped_newline %{ entity = INTERNAL_NL; } %d_ccallback
84       |
85       ws
86       |
87       [^\t '\\] @code
88       |
89       '\\' nonnewline @code
90     )* '\'';
91   d_dq_str =
92     '"' @code (
93       escaped_newline %{ entity = INTERNAL_NL; } %d_ccallback
94       |
95       ws
96       |
97       [^\t "\\] @code
98       |
99       '\\' nonnewline @code
100     )* '"';
101   d_bt_str =
102     '`' @code (
103       escaped_newline %{ entity = INTERNAL_NL; } %d_ccallback
104       |
105       ws
106       |
107       [^\t `\\] @code
108       |
109       '\\' nonnewline @code
110     )* '`';
111   d_string = d_sq_str | d_dq_str | d_bt_str;
112
113   d_line := |*
114     spaces    ${ entity = D_SPACE; } => d_ccallback;
115     d_comment;
116     d_string;
117     newline   ${ entity = NEWLINE; } => d_ccallback;
118     ^space    ${ entity = D_ANY;   } => d_ccallback;
119   *|;
120
121   # Entity machine
122
123   action d_ecallback {
124     callback(D_LANG, d_entities[entity], cint(ts), cint(te), userdata);
125   }
126
127   d_line_comment_entity = '//' (escaped_newline | nonnewline)*;
128   d_block_comment_entity = '/*' any* :>> '*/';
129   d_nested_comment_entity = '/+' >d_comment_nc_res (
130     '/+' @d_comment_nc_inc
131     |
132     '+/' @d_comment_nc_dec
133     |
134     any
135   )* :>> ('+/' when { nest_count == 0 });
136   d_comment_entity = d_line_comment_entity | d_block_comment_entity |
137     d_nested_comment_entity;
138
139   d_entity := |*
140     space+           ${ entity = D_SPACE;   } => d_ecallback;
141     d_comment_entity ${ entity = D_COMMENT; } => d_ecallback;
142     # TODO:
143     ^space;
144   *|;
145 }%%
146
147 /************************* Required for every parser *************************/
148
149 /* Parses a string buffer with D code.
150  *
151  * @param *buffer The string to parse.
152  * @param length The length of the string to parse.
153  * @param count Integer flag specifying whether or not to count lines. If yes,
154  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
155  *   machine optimized for returning entity positions.
156  * @param *callback Callback function. If count is set, callback is called for
157  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
158  *   'lblank' respectively. Otherwise callback is called for each entity found.
159  */
160 void parse_d(char *buffer, int length, int count,
161              void (*callback) (const char *lang, const char *entity, int s,
162                                int e, void *udata),
163              void *userdata
164   ) {
165   init
166
167   int nest_count = 0;
168
169   %% write init;
170   cs = (count) ? d_en_d_line : d_en_d_entity;
171   %% write exec;
172
173   // if no newline at EOF; callback contents of last line
174   if (count) { process_last_line(D_LANG) }
175 }
176
177 #endif
178
179 /*****************************************************************************/