OTWO-1213 Works around lost encoding in Ruby/C binding layer
[ohcount] / src / parsers / php.rl
1 // php.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_PHP_PARSER_H
5 #define OHCOUNT_PHP_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *PHP_LANG = LANG_PHP;
11
12 // the languages entities
13 const char *php_entities[] = {
14   "space", "comment", "string", "any"
15 };
16
17 // constants associated with the entities
18 enum {
19   PHP_SPACE = 0, PHP_COMMENT, PHP_STRING, PHP_ANY
20 };
21
22 /*****************************************************************************/
23
24 %%{
25   machine php;
26   write data;
27   include common "common.rl";
28
29   # Line counting machine
30
31   action php_ccallback {
32     switch(entity) {
33     case PHP_SPACE:
34       ls
35       break;
36     case PHP_ANY:
37       code
38       break;
39     case INTERNAL_NL:
40       std_internal_newline(PHP_LANG)
41       break;
42     case NEWLINE:
43       std_newline(PHP_LANG)
44     }
45   }
46
47   php_line_comment = ('//' | '#') @comment nonnewline*;
48   php_block_comment =
49     '/*' @comment (
50       newline %{ entity = INTERNAL_NL; } %php_ccallback
51       |
52       ws
53       |
54       (nonnewline - ws) @comment
55     )* :>> '*/';
56   php_comment = php_line_comment | php_block_comment;
57
58   php_sq_str =
59     '\'' @enqueue @code (
60       newline %{ entity = INTERNAL_NL; } %php_ccallback
61       |
62       ws
63       |
64       [^\r\n\f'\\] @code
65       |
66       '\\' nonnewline @code
67     )* '\'' @commit @code;
68   php_dq_str =
69     '"' @enqueue @code (
70       newline %{ entity = INTERNAL_NL; } %php_ccallback
71       |
72       ws
73       |
74       [^\r\n\f"\\] @code
75       |
76       '\\' nonnewline @code
77     )* '"' @commit @code;
78   # TODO: heredoc; see ruby.rl for details.
79   php_string = php_sq_str | php_dq_str;
80
81   php_line := |*
82     spaces       ${ entity = PHP_SPACE; } => php_ccallback;
83     php_comment;
84     php_string;
85     newline      ${ entity = NEWLINE;   } => php_ccallback;
86     ^space       ${ entity = PHP_ANY;   } => php_ccallback;
87   *|;
88
89   # Entity machine
90
91   action php_ecallback {
92     callback(PHP_LANG, php_entities[entity], cint(ts), cint(te), userdata);
93   }
94
95   php_line_comment_entity = ('#' | '//') nonnewline*;
96   php_block_comment_entity = '/*' any* :>> '*/';
97   php_comment_entity = php_line_comment_entity | php_block_comment_entity;
98
99   php_entity := |*
100     space+             ${ entity = PHP_SPACE;   } => php_ecallback;
101     php_comment_entity ${ entity = PHP_COMMENT; } => php_ecallback;
102     # TODO:
103     ^space;
104   *|;
105 }%%
106
107 /************************* Required for every parser *************************/
108
109 /* Parses a string buffer with PHP code (not in HTML).
110  *
111  * @param *buffer The string to parse.
112  * @param length The length of the string to parse.
113  * @param count Integer flag specifying whether or not to count lines. If yes,
114  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
115  *   machine optimized for returning entity positions.
116  * @param *callback Callback function. If count is set, callback is called for
117  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
118  *   'lblank' respectively. Otherwise callback is called for each entity found.
119  */
120 void parse_php(char *buffer, int length, int count,
121                void (*callback) (const char *lang, const char *entity, int s,
122                                  int e, void *udata),
123                void *userdata
124   ) {
125   init
126
127   %% write init;
128   cs = (count) ? php_en_php_line : php_en_php_entity;
129   %% write exec;
130
131   // if no newline at EOF; callback contents of last line
132   if (count) { process_last_line(PHP_LANG) }
133 }
134
135 #endif
136
137 /*****************************************************************************/