OTWO-1213 Works around lost encoding in Ruby/C binding layer
[ohcount] / src / parsers / nix.rl
1 /************************* Required for every parser *************************/
2 #ifndef OHCOUNT_NIX_PARSER_H
3 #define OHCOUNT_NIX_PARSER_H
4
5 #include "../parser_macros.h"
6
7 // the name of the language
8 const char *NIX_LANG = LANG_NIX;
9
10 // the languages entities
11 const char *nix_entities[] = {
12   "space", "comment", "any"
13 };
14
15 // constants associated with the entities
16 enum {
17   NIX_SPACE = 0, NIX_COMMENT, NIX_ANY
18 };
19
20 /*****************************************************************************/
21
22 #include "shell.h"
23
24 %%{
25   machine nix;
26   write data;
27   include common "common.rl";
28   #EMBED(shell)
29
30   # Line counting machine
31
32   action nix_ccallback {
33     switch(entity) {
34     case NIX_SPACE:
35       ls
36       break;
37     case NIX_ANY:
38       code
39       break;
40     case INTERNAL_NL:
41       std_internal_newline(NIX_LANG)
42       break;
43     case NEWLINE:
44       std_newline(NIX_LANG)
45       break;
46     case CHECK_BLANK_ENTRY:
47       check_blank_entry(NIX_LANG)
48     }
49   }
50
51   nix_line_comment = '#' @comment nonnewline*;
52
53   nix_block_comment =
54     '/*' @comment (
55       newline %{ entity = INTERNAL_NL; } %nix_ccallback
56       |
57       ws
58       |
59       (nonnewline - ws) @comment
60     )* :>> '*/';
61
62   nix_comment = nix_line_comment | nix_block_comment;
63
64   nix_dq_shell_entry = '"' @code;
65   nix_dq_shell_outry = '"' @check_blank_outry @code;
66   nix_dq_shell_line := |*
67     nix_dq_shell_outry @{ p = ts; fret; };
68     # TODO: Add embeded Nix between '${' and '}'
69     # unmodified SHELL patterns
70     spaces         ${ entity = SHELL_SPACE; } => shell_ccallback;
71     shell_comment;
72     shell_string;
73     newline        ${ entity = NEWLINE;     } => shell_ccallback;
74     ^space         ${ entity = SHELL_ANY;   } => shell_ccallback;
75   *|;
76
77   nix_dsq_shell_entry = "''" @code;
78   nix_dsq_shell_outry = "''" @check_blank_outry @code;
79   nix_dsq_shell_line := |*
80     nix_dsq_shell_outry @{ p = ts; fret; };
81     # TODO: Add embeded Nix between '${' and '}'
82     # unmodified SHELL patterns
83     spaces         ${ entity = SHELL_SPACE; } => shell_ccallback;
84     shell_comment;
85     shell_string;
86     newline        ${ entity = NEWLINE;     } => shell_ccallback;
87     ^space         ${ entity = SHELL_ANY;   } => shell_ccallback;
88   *|;
89
90   nix_line := |*
91     nix_dq_shell_entry @{ entity = CHECK_BLANK_ENTRY; } @nix_ccallback
92       @{ saw(SHELL_LANG); } => { fcall nix_dq_shell_line; };
93     nix_dsq_shell_entry @{ entity = CHECK_BLANK_ENTRY; } @nix_ccallback
94       @{ saw(SHELL_LANG); } => { fcall nix_dsq_shell_line; };
95     # NIX patterns
96     spaces    ${ entity = NIX_SPACE; } => nix_ccallback;
97     nix_comment;
98     newline   ${ entity = NEWLINE; } => nix_ccallback;
99     ^space    ${ entity = NIX_ANY;   } => nix_ccallback;
100   *|;
101
102   # Entity machine
103
104   action nix_ecallback {
105     callback(NIX_LANG, nix_entities[entity], cint(ts), cint(te), userdata);
106   }
107
108   nix_line_comment_entity = '#' nonnewline*;
109   nix_block_comment_entity = '/*' any* :>> '*/';
110   nix_comment_entity = nix_line_comment_entity | nix_block_comment_entity;
111
112
113   nix_dq_shell_entry_entity = '"';
114   nix_dq_shell_outry_entity = '"';
115   nix_dq_shell_entity := |*
116     nix_dq_shell_outry_entity @{ fret; };
117     # TODO: Add embeded Nix between '${' and '}'
118     # unmodified SHELL patterns
119     space+               ${ entity = SHELL_SPACE;   } => shell_ecallback;
120     shell_comment_entity ${ entity = SHELL_COMMENT; } => shell_ecallback;
121     # TODO:
122     ^space;
123   *|;
124
125   nix_dsq_shell_entry_entity = "''";
126   nix_dsq_shell_outry_entity = "''";
127   nix_dsq_shell_entity := |*
128     nix_dsq_shell_outry_entity @{ fret; };
129     # TODO: Add embeded Nix between '${' and '}'
130     # unmodified SHELL patterns
131     space+               ${ entity = SHELL_SPACE;   } => shell_ecallback;
132     shell_comment_entity ${ entity = SHELL_COMMENT; } => shell_ecallback;
133     # TODO:
134     ^space;
135   *|;
136
137   nix_entity := |*
138     nix_dq_shell_entry_entity  => { fcall nix_dq_shell_entity;  };
139     nix_dsq_shell_entry_entity => { fcall nix_dsq_shell_entity; };
140     space+             ${ entity = NIX_SPACE;   } => nix_ecallback;
141     nix_comment_entity ${ entity = NIX_COMMENT; } => nix_ecallback;
142     # TODO;
143     ^space;
144   *|;
145 }%%
146
147 /************************* Required for every parser *************************/
148
149 /* Parses a string buffer with Nix 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_nix(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   %% write init;
168   cs = (count) ? nix_en_nix_line : nix_en_nix_entity;
169   %% write exec;
170
171   // if no newline at EOF; callback contents of last line
172   if (count) { process_last_line(NIX_LANG) }
173 }
174
175 #endif
176
177 /*****************************************************************************/