Initial import of files for generating Doxygen documentation.
[ohcount] / src / parsers / glsl.rl
1 // glsl.rl by Leszek Godlewski <ineqvation ay tee gmail dee oh tee cee oh em>
2 // Written according to GLSL 1.20.8 specificiation
3 // Based on c.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
4
5 /************************* Required for every parser *************************/
6 #ifndef OHCOUNT_GLSL_PARSER_H
7 #define OHCOUNT_GLSL_PARSER_H
8
9 #include "../parser_macros.h"
10
11 // the name of the language
12 const char *GLSL_LANG = LANG_GLSL;
13
14 // the languages entities
15 const char *glsl_entities[] = {
16   "space", "comment", "string", "number", "preproc",
17   "keyword", "identifier", "operator", "any"
18 };
19
20 // constants associated with the entities
21 enum {
22   GLSL_SPACE = 0, GLSL_COMMENT, GLSL_STRING, GLSL_NUMBER, GLSL_PREPROC,
23   GLSL_KEYWORD, GLSL_IDENTIFIER, GLSL_OPERATOR, GLSL_ANY
24 };
25
26 /*****************************************************************************/
27
28 %%{
29   machine glsl;
30   write data;
31   include common "common.rl";
32
33   # Line counting machine
34
35   action glsl_ccallback {
36     switch(entity) {
37     case GLSL_SPACE:
38       ls
39       break;
40     case GLSL_ANY:
41       code
42       break;
43     case INTERNAL_NL:
44       std_internal_newline(GLSL_LANG)
45       break;
46     case NEWLINE:
47       std_newline(GLSL_LANG)
48     }
49   }
50
51   glsl_line_comment =
52     '//' @comment (
53       escaped_newline %{ entity = INTERNAL_NL; } %glsl_ccallback
54       |
55       ws
56       |
57       (nonnewline - ws) @comment
58     )*;
59   glsl_block_comment =
60     '/*' @comment (
61       newline %{ entity = INTERNAL_NL; } %glsl_ccallback
62       |
63       ws
64       |
65       (nonnewline - ws) @comment
66     )* :>> '*/';
67   glsl_comment = glsl_line_comment | glsl_block_comment;
68
69   glsl_sq_str =
70     '\'' @code (
71       escaped_newline %{ entity = INTERNAL_NL; } %glsl_ccallback
72       |
73       ws
74       |
75       [^\t '\\] @code
76       |
77       '\\' nonnewline @code
78     )* '\'';
79   glsl_dq_str =
80     '"' @code (
81       escaped_newline %{ entity = INTERNAL_NL; } %glsl_ccallback
82       |
83       ws
84       |
85       [^\t "\\] @code
86       |
87       '\\' nonnewline @code
88     )* '"';
89   glsl_string = glsl_sq_str | glsl_dq_str;
90
91   glsl_line := |*
92     spaces    ${ entity = GLSL_SPACE; } => glsl_ccallback;
93     glsl_comment;
94     glsl_string;
95     newline   ${ entity = NEWLINE; } => glsl_ccallback;
96     ^space    ${ entity = GLSL_ANY;   } => glsl_ccallback;
97   *|;
98
99   # Entity machine
100
101   action glsl_ecallback {
102     callback(GLSL_LANG, glsl_entities[entity], cint(ts), cint(te), userdata);
103   }
104
105   glsl_line_comment_entity = '//' (escaped_newline | nonnewline)*;
106   glsl_block_comment_entity = '/*' any* :>> '*/';
107   glsl_comment_entity = glsl_line_comment_entity | glsl_block_comment_entity;
108
109   glsl_string_entity = sq_str_with_escapes | dq_str_with_escapes;
110
111   glsl_number_entity = float | integer;
112
113   glsl_preproc_word =
114   # macros
115     'define' | 'undef' |
116   # conditionals
117     'if' | 'ifdef' | 'ifndef' | 'else' | 'elif' | 'endif' |
118   # miscellanous
119     'pragma' | 'error' | 'extension' | 'version' | 'line';
120   # TODO: find some way of making preproc match the beginning of a line.
121   # Putting a 'when starts_line' conditional throws an assertion error.
122   glsl_preproc_entity =
123     '#' space* (glsl_block_comment_entity space*)?
124       glsl_preproc_word (escaped_newline | nonnewline)*;
125
126   glsl_identifier_entity = (alpha | '_') (alnum | '_')*;
127
128   glsl_keyword_entity =
129     'attribute' | 'const' | 'uniform' | 'varying' | 'centroid' | 'break' |
130     'continue' | 'do' | 'for' | 'while' | 'if' | 'else' | 'in' | 'out' |
131     'inout' | 'float' | 'int' | 'void' | 'bool' | 'true' | 'false' |
132     'invariant' | 'discard' | 'return' | 'mat2' | 'mat3' | 'mat4' |
133     'mat2x2' | 'mat2x3' | 'mat2x4' | 'mat3x2' | 'mat3x3' | 'mat3x4' |
134     'mat4x2' | 'mat4x3' | 'mat4x4' | 'vec2' | 'vec3' | 'vec4' | 'ivec2' |
135     'ivec3' | 'ivec4' | 'bvec2' | 'bvec3' | 'bvec4' | 'sampler1D' |
136     'sampler2D' | 'sampler3D' | 'samplerCube' | 'sampler1DShadow' |
137     'sampler2DShadow' | 'struct';
138   # not including keywords reserved for future use
139
140   glsl_operator_entity = [+\-/*%<>!=^&|?~:;.,()\[\]{}];
141
142   glsl_entity := |*
143     space+                 ${ entity = GLSL_SPACE;      } => glsl_ecallback;
144     glsl_comment_entity    ${ entity = GLSL_COMMENT;    } => glsl_ecallback;
145     glsl_string_entity     ${ entity = GLSL_STRING;     } => glsl_ecallback;
146     glsl_number_entity     ${ entity = GLSL_NUMBER;     } => glsl_ecallback;
147     glsl_preproc_entity    ${ entity = GLSL_PREPROC;    } => glsl_ecallback;
148     glsl_identifier_entity ${ entity = GLSL_IDENTIFIER; } => glsl_ecallback;
149     glsl_keyword_entity    ${ entity = GLSL_KEYWORD;    } => glsl_ecallback;
150     glsl_operator_entity   ${ entity = GLSL_OPERATOR;   } => glsl_ecallback;
151     ^(space | digit)       ${ entity = GLSL_ANY;        } => glsl_ecallback;
152   *|;
153 }%%
154
155 /************************* Required for every parser *************************/
156
157 /* Parses a string buffer with OpenGL Shading Language code.
158  *
159  * @param *buffer The string to parse.
160  * @param length The length of the string to parse.
161  * @param count Integer flag specifying whether or not to count lines. If yes,
162  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
163  *   machine optimized for returning entity positions.
164  * @param *callback Callback function. If count is set, callback is called for
165  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
166  *   'lblank' respectively. Otherwise callback is called for each entity found.
167  */
168 void parse_glsl(char *buffer, int length, int count,
169                 void (*callback) (const char *lang, const char *entity, int s,
170                                   int e, void *udata),
171                 void *userdata
172   ) {
173   init
174
175   %% write init;
176   cs = (count) ? glsl_en_glsl_line : glsl_en_glsl_entity;
177   %% write exec;
178
179   // if no newline at EOF; callback contents of last line
180   if (count) { process_last_line(GLSL_LANG) }
181 }
182
183 #endif
184
185 /*****************************************************************************/