Fixes recursion bug in disambiguate_in().
[ohcount] / src / parsers / metapost_with_tex.rl
1 // mp_with_tex.rl written by Mitchell Foral. mitchell<att>caladbolg<dott>net.
2
3 /************************* Required for every parser *************************/
4 #ifndef OHCOUNT_MPTEX_PARSER_H
5 #define OHCOUNT_MPTEX_PARSER_H
6
7 #include "../parser_macros.h"
8
9 // the name of the language
10 const char *MPTEX_LANG = LANG_METAPOST;
11
12 // the languages entities
13 const char *mptex_entities[] = {
14   "space", "comment", "string", "any"
15 };
16
17
18 // constants associated with the entities
19 enum {
20   MPTEX_SPACE = 0, MPTEX_COMMENT, MPTEX_STRING, MPTEX_ANY
21 };
22
23 /*****************************************************************************/
24
25 #include "tex.h"
26
27 %%{
28   machine mptex;
29   write data;
30   include common "common.rl";
31   #EMBED(tex)
32
33   # Line counting machine
34
35   action mptex_ccallback {
36     switch(entity) {
37     case MPTEX_SPACE:
38       ls
39       break;
40     case MPTEX_ANY:
41       code
42       break;
43     case INTERNAL_NL:
44       std_internal_newline(MPTEX_LANG)
45       break;
46     case NEWLINE:
47       std_newline(MPTEX_LANG)
48       break;
49     case CHECK_BLANK_ENTRY:
50       check_blank_entry(MPTEX_LANG)
51     }
52   }
53
54   mptex_comment = '%' @{ fhold; } @comment nonnewline*;
55
56   mptex_string = '"' @code ([^\r\n\f"\\] | '\\' nonnewline)* '"';
57
58   mptex_tex_entry = ('verbatimtex' | 'btex') @code;
59   mptex_tex_outry = 'etex' @check_blank_outry @code;
60   mptex_tex_line := |*
61     mptex_tex_outry @{ p = ts; fret; };
62     # unmodified Tex patterns
63     spaces       ${ entity = TEX_SPACE; } => tex_ccallback;
64     tex_comment;
65     newline      ${ entity = NEWLINE;   } => tex_ccallback;
66     ^space       ${ entity = TEX_ANY;   } => tex_ccallback;
67   *|;
68
69   mptex_line := |*
70     mptex_tex_entry @{ entity = CHECK_BLANK_ENTRY; } @mptex_ccallback
71       @{ saw(TEX_LANG); } => { fcall mptex_tex_line; };
72     # standard Metapost patterns
73     spaces            ${ entity = MPTEX_SPACE; } => mptex_ccallback;
74     mptex_comment;
75     mptex_string;
76     newline           ${ entity = NEWLINE;        } => mptex_ccallback;
77     ^space            ${ entity = MPTEX_ANY;   } => mptex_ccallback;
78   *|;
79
80   # Entity machine
81
82   action mptex_ecallback {
83     callback(MPTEX_LANG, mptex_entities[entity], cint(ts), cint(te), userdata);
84   }
85
86   mptex_tex_entry_entity = 'verbatimtex' | 'btex';
87   mptex_tex_outry_entity = 'etex';
88   mptex_tex_entity := |*
89     mptex_tex_outry_entity @{ fret; };
90     # unmodified Tex patterns
91     space+             ${ entity = TEX_SPACE;   } => tex_ecallback;
92     tex_comment_entity ${ entity = TEX_COMMENT; } => tex_ecallback;
93     # TODO:
94     ^space;
95   *|;
96
97   mptex_comment_entity = '%' nonnewline*;
98
99   mptex_entity := |*
100     # TODO: mptex_ecallback for mptex_*_{entry,outry}_entity
101     mptex_tex_entry_entity => { fcall mptex_tex_entity; };
102     # standard mptex patterns
103     space+               ${ entity = MPTEX_SPACE;   } => mptex_ecallback;
104     mptex_comment_entity ${ entity = MPTEX_COMMENT; } => mptex_ecallback;
105     # TODO:
106     ^space;
107   *|;
108 }%%
109
110 /************************* Required for every parser *************************/
111
112 /* Parses a string buffer with Metapost code.
113  *
114  * @param *buffer The string to parse.
115  * @param length The length of the string to parse.
116  * @param count Integer flag specifying whether or not to count lines. If yes,
117  *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
118  *   machine optimized for returning entity positions.
119  * @param *callback Callback function. If count is set, callback is called for
120  *   every line of code, comment, or blank with 'lcode', 'lcomment', and
121  *   'lblank' respectively. Otherwise callback is called for each entity found.
122  */
123 void parse_mptex(char *buffer, int length, int count,
124                  void (*callback) (const char *lang, const char *entity, int s,
125                                    int e, void *udata),
126                  void *userdata
127   ) {
128   init
129
130   %% write init;
131   cs = (count) ? mptex_en_mptex_line : mptex_en_mptex_entity;
132   %% write exec;
133
134   // if no newline at EOF; callback contents of last line
135   if (count) { process_last_line(MPTEX_LANG) }
136 }
137
138 #endif
139
140 /*****************************************************************************/