4 // BEGIN parser includes
6 #include "lua_parser.h"
14 char name[MAX_LANGUAGE_NAME];
15 void (*parser) (char*, int, int, void*);
18 struct language languages[] = {
27 /* Returns a language_breakdown for a given language name. */
28 LanguageBreakdown *get_language_breakdown(char *name) {
30 for (i = 0; i < pr->language_breakdown_count; i++)
31 if (strcmp(pr->language_breakdowns[i].name, name) == 0)
32 return &pr->language_breakdowns[i]; // found one
34 language_breakdown_initialize(
35 &pr->language_breakdowns[pr->language_breakdown_count],
36 name, parse_buffer_len); // create one
37 return &pr->language_breakdowns[pr->language_breakdown_count++];
40 /* Yields a line's language, semantic, and text to an optional Ruby block. */
41 void ragel_parse_yield_line(const char *lang, const char *entity, int s, int e) {
42 if (rb_block_given_p()) {
45 rb_ary_store(ary, 0, ID2SYM(rb_intern(lang)));
46 if (strcmp(entity, "lcode") == 0)
47 rb_ary_store(ary, 1, ID2SYM(rb_intern("code")));
48 else if (strcmp(entity, "lcomment") == 0)
49 rb_ary_store(ary, 1, ID2SYM(rb_intern("comment")));
50 else if (strcmp(entity, "lblank") == 0)
51 rb_ary_store(ary, 1, ID2SYM(rb_intern("blank")));
52 rb_ary_store(ary, 2, rb_str_new(parse_buffer + s, e - s));
57 /* Callback function called for every entity in the source file discovered.
59 * Entities are defined in the parser and are things like comments, strings,
61 * This callback yields for a Ruby block if necessary:
62 * |language, semantic, line|
63 * @param *lang The language associated with the entity.
64 * @param *entity The entity discovered. There are 3 additional entities used
65 * by Ohcount for counting: lcode, lcomment, and lblank for a line of code,
66 * a whole line comment, or a blank line respectively.
67 * @param s The start position of the entity relative to the start of the
69 * @param e The end position of the entity relative to the start of the buffer
72 void ragel_parser_callback(const char *lang, const char *entity, int s, int e) {
73 LanguageBreakdown *lb = get_language_breakdown((char *) lang);
74 if (strcmp(entity, "lcode") == 0) {
75 language_breakdown_copy_code(lb, parse_buffer + s, parse_buffer + e);
76 ragel_parse_yield_line(lang, entity, s, e);
77 } else if (strcmp(entity, "lcomment") == 0) {
78 language_breakdown_copy_comment(lb, parse_buffer + s, parse_buffer + e);
79 ragel_parse_yield_line(lang, entity, s, e);
80 } else if (strcmp(entity, "lblank") == 0) {
82 ragel_parse_yield_line(lang, entity, s, e);
86 /* Tries to use an existing Ragel parser for the given language.
88 * @param *parse_result An allocated, empty ParseResult to hold parse results.
89 * @param *buffer A pointer to the buffer or character in the buffer to start
91 * @param buffer_len The length of the buffer to parse.
92 * @param *lang The language name associated with the buffer to parse.
93 * @return 1 if a Ragel parser is found, 0 otherwise.
95 int ragel_parser_parse(ParseResult *parse_result,
96 char *buffer, int buffer_len, char *lang) {
98 pr->language_breakdown_count = 0;
99 parse_buffer = buffer;
100 parse_buffer_len = buffer_len;
102 for (i = 0; strlen(languages[i].name) != 0; i++)
103 if (strcmp(languages[i].name, lang) == 0) {
104 languages[i].parser(buffer, buffer_len, 1, ragel_parser_callback);