Merge pull request #41 from blackducksw/ubuntu_14
[ohcount] / src / parsers / forth.rl
1 // forth.rl 
2 // derived from code written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
3
4 /************************* Required for every parser *************************/
5 #ifndef OHCOUNT_FORTH_PARSER_H
6 #define OHCOUNT_FORTH_PARSER_H
7
8 #include "../parser_macros.h"
9
10 // the name of the language
11 const char *FORTH_LANG = LANG_FORTH;
12
13 // the languages entities
14 const char *forth_entities[] = {
15   "space", "comment", "string", "any",
16 };
17
18 // constants associated with the entities
19 enum {
20   FORTH_SPACE = 0, FORTH_COMMENT, FORTH_STRING, FORTH_ANY
21 };
22
23 /*****************************************************************************/
24
25 %%{
26   machine forth;
27   write data;
28   include common "common.rl";
29
30   # Line counting machine
31
32   action forth_ccallback {
33     switch(entity) {
34     case FORTH_SPACE:
35       ls
36       break;
37     case FORTH_ANY:
38       code
39       break;
40     case INTERNAL_NL:
41       std_internal_newline(FORTH_LANG)
42       break;
43     case NEWLINE:
44       std_newline(FORTH_LANG)
45     }
46   }
47
48   forth_line_comment = '\\' @comment nonnewline*;
49   forth_block_comment =
50     '(' @comment (
51       newline %{ entity = INTERNAL_NL; } %forth_ccallback
52       |
53       ws
54       |
55       (nonnewline - ws) @comment
56     )* :>> ')';
57   forth_comment = forth_line_comment | forth_block_comment;
58
59   forth_string = '"' @code ([^\r\n\f"])* '"';
60
61   forth_line := |*
62     spaces         ${ entity = FORTH_SPACE; } => forth_ccallback;
63     forth_comment;
64     forth_string;
65     newline        ${ entity = NEWLINE;     } => forth_ccallback;
66     ^space         ${ entity = FORTH_ANY;   } => forth_ccallback;
67   *|;
68
69   # Entity machine
70
71   action forth_ecallback {
72     callback(FORTH_LANG, forth_entities[entity], cint(ts), cint(te), userdata);
73   }
74
75   forth_line_comment_entity = '\\' nonnewline*;
76   forth_block_comment_entity = '(' any* :>> ')';
77   forth_comment_entity = forth_line_comment_entity | forth_block_comment_entity;
78
79   forth_entity := |*
80     space+               ${ entity = FORTH_SPACE;   } => forth_ecallback;
81     forth_comment_entity ${ entity = FORTH_COMMENT; } => forth_ecallback;
82     # TODO:
83     ^space;
84   *|;
85 }%%
86
87 /************************* Required for every parser *************************/
88
89 /* Parses a string buffer with Forth code.
90  *
91  * @param *buffer The string to parse.
92  * @param length The length of the string to parse.
93  * @param count Integer flag specifying whether or not to count lines. If yes,
94  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
95  *   machine optimized for returning entity positions.
96  * @param *callback Callback function. If count is set, callback is called for
97  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
98  *   'lblank' respectively. Otherwise callback is called for each entity found.
99  */
100 void parse_forth(char *buffer, int length, int count,
101                  void (*callback) (const char *lang, const char *entity, int s,
102                                    int e, void *udata),
103                  void *userdata
104   ) {
105   init
106
107   %% write init;
108   cs = (count) ? forth_en_forth_line : forth_en_forth_entity;
109   %% write exec;
110
111   // if no newline at EOF; callback contents of last line
112   if (count) { process_last_line(FORTH_LANG) }
113 }
114
115 #endif
116
117 /*****************************************************************************/