OTWO-1213 Works around lost encoding in Ruby/C binding layer
[ohcount] / src / parsers / assembler.rl
1 // assembler.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_ASM_PARSER_H
5 #define OHCOUNT_ASM_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *ASM_LANG = LANG_ASSEMBLER;
11
12 // the languages entities
13 const char *asm_entities[] = {
14   "space", "comment", "string", "number",
15   "keyword", "identifier", "operator", "any"
16 };
17
18 // constants associated with the entities
19 enum {
20   ASM_SPACE = 0, ASM_COMMENT, ASM_STRING, ASM_NUMBER,
21   ASM_KEYWORD, ASM_IDENTIFIER, ASM_OPERATOR, ASM_ANY
22 };
23
24 /*****************************************************************************/
25
26 %%{
27   machine assembler;
28   write data;
29   include common "common.rl";
30
31   # Line counting machine
32
33   action asm_ccallback {
34     switch(entity) {
35     case ASM_SPACE:
36       ls
37       break;
38     case ASM_ANY:
39       code
40       break;
41     case INTERNAL_NL:
42       std_internal_newline(ASM_LANG)
43       break;
44     case NEWLINE:
45       std_newline(ASM_LANG)
46     }
47   }
48
49   asm_line_comment = ('//' | ';' | '!') @comment nonnewline*;
50   asm_block_comment =
51     '/*' @comment (
52       newline %{ entity = INTERNAL_NL; } %asm_ccallback
53       |
54       ws
55       |
56       (nonnewline - ws) @comment
57     )* :>> '*/';
58   asm_comment = asm_line_comment | asm_block_comment;
59
60   asm_string = '"' @code ([^\r\n\f"\\] | '\\' nonnewline)* '"';
61
62   asm_line := |*
63     spaces       ${ entity = ASM_SPACE; } => asm_ccallback;
64     asm_comment;
65     asm_string;
66     newline      ${ entity = NEWLINE;   } => asm_ccallback;
67     ^space       ${ entity = ASM_ANY;   } => asm_ccallback;
68   *|;
69
70   # Entity machine
71
72   action asm_ecallback {
73     callback(ASM_LANG, asm_entities[entity], cint(ts), cint(te), userdata);
74   }
75
76   asm_line_comment_entity = ('//' | ';' | '!') nonnewline*;
77   asm_block_comment_entity = '/*' any* :>> '*/';
78   asm_comment_entity = asm_line_comment_entity | asm_block_comment_entity;
79
80   asm_entity := |*
81     space+             ${ entity = ASM_SPACE;   } => asm_ecallback;
82     asm_comment_entity ${ entity = ASM_COMMENT; } => asm_ecallback;
83     # TODO:
84     ^space;
85   *|;
86 }%%
87
88 /************************* Required for every parser *************************/
89
90 /* Parses a string buffer with Assembler code.
91  *
92  * @param *buffer The string to parse.
93  * @param length The length of the string to parse.
94  * @param count Integer flag specifying whether or not to count lines. If yes,
95  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
96  *   machine optimized for returning entity positions.
97  * @param *callback Callback function. If count is set, callback is called for
98  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
99  *   'lblank' respectively. Otherwise callback is called for each entity found.
100  */
101 void parse_assembler(char *buffer, int length, int count,
102                      void (*callback) (const char *lang, const char *entity,
103                                        int s, int e, void *udata),
104                      void *userdata
105   ) {
106   init
107
108   %% write init;
109   cs = (count) ? assembler_en_asm_line : assembler_en_asm_entity;
110   %% write exec;
111
112   // if no newline at EOF; callback contents of last line
113   if (count) { process_last_line(ASM_LANG) }
114 }
115
116 #endif
117
118 /*****************************************************************************/