2 /************************************************************************
4 * Copyright 2012 Jonatan Liljedahl <lijon@kymatica.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 ************************************************************************/
26 //#define YYLEX_PARAM &yylval, &yylloc
30 extern
int scdoclineno
;
31 extern
char *scdoctext
;
32 extern
int scdoc_start_token
;
34 //extern struct YYLTYPE scdoclloc;
36 //int scdoc_metadata_mode;
38 static const char * method_type
= NULL
;
40 static DocNode
* topnode
;
42 void scdocerror
(const char *str
);
44 extern
void error(const char *fmt
, ...
);
45 extern
void post
(const char *fmt
, ...
);
56 // single line header tags that take text
57 %token CLASS TITLE SUMMARY RELATED CATEGORIES REDIRECT
58 // single line body tags that take text
59 %token CLASSTREE COPYMETHOD KEYWORD PRIVATE
60 // single line structural tags that take text, with children
61 %token SECTION SUBSECTION METHOD ARGUMENT
62 // single line structural tags with no text, with children
63 %token DESCRIPTION CLASSMETHODS INSTANCEMETHODS EXAMPLES RETURNS DISCUSSION
64 // nestable range tags with no text, with children
65 %token LIST TREE NUMBEREDLIST DEFINITIONLIST TABLE FOOTNOTE NOTE WARNING
66 // modal range tags that take multi-line text
67 %token CODE LINK ANCHOR SOFT IMAGE TELETYPE MATH STRONG EMPHASIS
68 %token CODEBLOCK
"CODE block" TELETYPEBLOCK
"TELETYPE block" MATHBLOCK
"MATH block"
70 %token TAGSYM
"::" BARS
"||" HASHES
"##"
71 // text and whitespace
72 %token
<str
> TEXT
"text" URL COMMA METHODNAME
"method name" METHODARGS
"arguments string"
73 %token NEWLINE
"newline" EMPTYLINES
"empty lines"
74 %token BAD_METHODNAME
"bad method name"
76 %token END
0 "end of file"
78 %type
<id
> headtag sectiontag listtag rangetag inlinetag blocktag
79 %type
<str
> anyword words anywordnl wordsnl anywordurl words2 nocommawords optMETHODARGS methodname
80 %type
<doc_node
> document arg optreturns optdiscussion body bodyelem
81 %type
<doc_node
> optsubsections optsubsubsections methodbody
82 %type
<doc_node
> dochead headline optsections sections section
83 %type
<doc_node
> subsections subsection subsubsection subsubsections
84 %type
<doc_node
> optbody optargs args listbody tablebody tablecells tablerow
85 %type
<doc_node
> prose proseelem blockA blockB commalist
86 %type
<doc_node
> deflistbody deflistrow defterms methnames
88 %token START_FULL START_PARTIAL START_METADATA
92 %destructor
{ doc_node_free_tree
($$
); } <doc_node
>
93 %destructor
{ free
($$
); } <str
>
96 //int scdoclex (YYSTYPE * yylval_param, struct YYLTYPE * yylloc_param );
102 start: document
{ topnode
= $1; }
103 | document
error { topnode
= NULL
; doc_node_free_tree
($1); }
106 document: START_FULL eateol dochead optsections
108 $$
= doc_node_create
("DOCUMENT");
109 doc_node_add_child
($$
, $3);
110 doc_node_add_child
($$
, $4);
112 | START_PARTIAL sections
114 $$
= doc_node_make_take_children
("BODY",NULL
,$2);
116 | START_METADATA dochead optsections
118 $$
= doc_node_create
("DOCUMENT");
119 doc_node_add_child
($$
, $2);
120 doc_node_add_child
($$
, $3);
128 dochead: dochead headline
{ $$
= doc_node_add_child
($1,$2); }
129 | headline
{ $$
= doc_node_make
("HEADER",NULL
,$1); }
132 headline: headtag words2 eol
{ $$
= doc_node_make
($1,$2,NULL
); }
133 | CATEGORIES commalist eol
{ $$
= doc_node_make_take_children
("CATEGORIES",NULL
,$2); }
134 | RELATED commalist eol
{ $$
= doc_node_make_take_children
("RELATED",NULL
,$2); }
137 headtag: CLASS
{ $$
= "TITLE"; } /* no need for the separate class:: tag actually. */
138 | TITLE
{ $$
= "TITLE"; }
139 | SUMMARY
{ $$
= "SUMMARY"; }
140 | REDIRECT
{ $$
= "REDIRECT"; }
143 sectiontag: CLASSMETHODS
{ $$
= "CLASSMETHODS"; method_type
= "CMETHOD"; }
144 | INSTANCEMETHODS
{ $$
= "INSTANCEMETHODS"; method_type
= "IMETHOD"; }
145 | DESCRIPTION
{ $$
= "DESCRIPTION"; method_type
= "METHOD"; }
146 | EXAMPLES
{ $$
= "EXAMPLES"; method_type
= "METHOD"; }
149 optsections: sections
150 |
{ $$
= doc_node_make
("BODY",NULL
,NULL
); }
153 sections: sections section
{ $$
= doc_node_add_child
($1,$2); }
154 | section
{ $$
= doc_node_make
("BODY",NULL
,$1); }
155 | subsubsections
{ $$
= doc_node_make_take_children
("BODY",NULL
,$1); } /* allow text before first section */
158 section: SECTION
{ method_type
= "METHOD"; } words2 eol optsubsections
{ $$
= doc_node_make_take_children
("SECTION",$3,$5); }
159 | sectiontag optsubsections
{ $$
= doc_node_make_take_children
($1, NULL
,$2); }
162 optsubsections: subsections
166 subsections: subsections subsection
{ $$
= doc_node_add_child
($1,$2); }
167 | subsection
{ $$
= doc_node_make
("(SUBSECTIONS)",NULL
,$1); }
171 subsection: SUBSECTION words2 eol optsubsubsections
{ $$
= doc_node_make_take_children
("SUBSECTION", $2, $4); }
174 optsubsubsections: subsubsections
178 subsubsections: subsubsections subsubsection
{ $$
= doc_node_add_child
($1,$2); }
179 | subsubsection
{ $$
= doc_node_make
("(SUBSUBSECTIONS)",NULL
,$1); }
180 | body
{ $$
= doc_node_make_take_children
("(SUBSUBSECTIONS)",NULL
,$1); }
183 subsubsection: METHOD methnames optMETHODARGS eol methodbody
185 $2->id
= "METHODNAMES";
186 $$
= doc_node_make
(method_type
,$3,$2);
187 doc_node_add_child
($$
, $5);
188 // doc_node_add_child($2, $3);
190 | COPYMETHOD words eol
{ $$
= doc_node_make
(
191 method_type
=="CMETHOD"?
"CCOPYMETHOD":(method_type
=="IMETHOD"?
"ICOPYMETHOD":"COPYMETHOD"),
194 | PRIVATE commalist eoleof
{ $$
= doc_node_make_take_children
(method_type
=="CMETHOD"?
"CPRIVATE":"IPRIVATE",NULL
,$2); }
197 optMETHODARGS: { $$
= NULL
; }
200 // $$ = doc_node_make("ARGSTRING",$1,NULL);
202 if
(method_type
!="METHOD") {
203 yyerror("METHOD argument string is not allowed inside CLASSMETHODS or INSTANCEMETHODS");
209 methodname: METHODNAME
211 char *p
= $1+strlen
($1)-1;
213 post
("WARNING: SCDoc: In %s\n Property setter %s should be documented without underscore.\n", scdoc_current_file
, $1);
220 methnames: methnames COMMA methodname
{ free
($2); $2 = NULL
; $$
= doc_node_add_child
($1, doc_node_make
("STRING",$3,NULL
)); }
221 | methodname
{ $$
= doc_node_make
("(METHODNAMES)",NULL
,doc_node_make
("STRING",$1,NULL
)); }
224 methodbody: optbody optargs optreturns optdiscussion
226 $$
= doc_node_make_take_children
("METHODBODY",NULL
,$1);
227 doc_node_add_child
($$
, $2);
228 doc_node_add_child
($$
, $3);
229 doc_node_add_child
($$
, $4);
241 args: args arg
{ $$
= doc_node_add_child
($1,$2); }
242 | arg
{ $$
= doc_node_make
("ARGUMENTS",NULL
,$1); }
245 arg: ARGUMENT words eol optbody
{ $$
= doc_node_make_take_children
("ARGUMENT", $2, $4); }
246 | ARGUMENT eol body
{ $$
= doc_node_make_take_children
("ARGUMENT", NULL
, $3); }
249 optreturns: RETURNS body
{ $$
= doc_node_make_take_children
("RETURNS",NULL
,$2); }
253 optdiscussion: DISCUSSION body
{ $$
= doc_node_make_take_children
("DISCUSSION",NULL
,$2); }
258 body contains a list of bodyelem's (A) and prose (B) such that
259 the list can start and end with either A or B, and A can repeat while B can not
266 blockA: blockB bodyelem
{ $$
= doc_node_add_child
($1,$2); }
267 | blockA bodyelem
{ $$
= doc_node_add_child
($1,$2); }
268 | bodyelem
{ $$
= doc_node_make
("(SECTIONBODY)",NULL
,$1); }
271 blockB: blockA prose
{ $$
= doc_node_add_child
($1,$2); }
272 | prose
{ $$
= doc_node_make
("(SECTIONBODY)",NULL
,$1); }
275 bodyelem: rangetag body TAGSYM
{ $$
= doc_node_make_take_children
($1,NULL
,$2); }
276 | listtag listbody TAGSYM
{ $$
= doc_node_make_take_children
($1,NULL
,$2); }
277 | TABLE tablebody TAGSYM
{ $$
= doc_node_make_take_children
("TABLE",NULL
,$2); }
278 | DEFINITIONLIST deflistbody TAGSYM
{ $$
= doc_node_make_take_children
("DEFINITIONLIST",NULL
,$2); }
279 | blocktag wordsnl TAGSYM
{ $$
= doc_node_make
($1,$2,NULL
); }
280 | CLASSTREE words eoleof
{ $$
= doc_node_make
("CLASSTREE",$2,NULL
); }
281 | KEYWORD commalist eoleof
{ $$
= doc_node_make_take_children
("KEYWORD",NULL
,$2);
282 // printf("keyword '%s'\n",$2->children[0]->text);
284 | EMPTYLINES
{ $$
= NULL
; }
285 | IMAGE words2 TAGSYM
{ $$
= doc_node_make
("IMAGE",$2,NULL
); }
288 prose: prose proseelem
{ $$
= doc_node_add_child
($1, $2); }
289 | proseelem
{ $$
= doc_node_make
("PROSE",NULL
,$1); }
292 proseelem: anyword
{ $$
= doc_node_make
(NODE_TEXT
,$1,NULL
); } // one TEXT for each word
293 | URL
{ $$
= doc_node_make
("LINK",$1,NULL
); }
294 | inlinetag words TAGSYM
{ $$
= doc_node_make
($1,$2,NULL
); }
295 | FOOTNOTE body TAGSYM
{ $$
= doc_node_make_take_children
("FOOTNOTE",NULL
,$2); }
296 | NEWLINE
{ $$
= doc_node_create
(NODE_NL
); }
299 inlinetag: LINK
{ $$
= "LINK"; }
300 | STRONG
{ $$
= "STRONG"; }
301 | SOFT
{ $$
= "SOFT"; }
302 | EMPHASIS
{ $$
= "EMPHASIS"; }
303 | CODE
{ $$
= "CODE"; }
304 | TELETYPE
{ $$
= "TELETYPE"; }
305 | MATH
{ $$
= "MATH"; }
306 | ANCHOR
{ $$
= "ANCHOR"; }
309 blocktag: CODEBLOCK
{ $$
= "CODEBLOCK"; }
310 | TELETYPEBLOCK
{ $$
= "TELETYPEBLOCK"; }
311 | MATHBLOCK
{ $$
= "MATHBLOCK"; }
314 listtag: LIST
{ $$
= "LIST"; }
315 | TREE
{ $$
= "TREE"; }
316 | NUMBEREDLIST
{ $$
= "NUMBEREDLIST"; }
319 rangetag: WARNING
{ $$
= "WARNING"; }
320 | NOTE
{ $$
= "NOTE"; }
323 listbody: listbody HASHES body
{ $$
= doc_node_add_child
($1, doc_node_make_take_children
("ITEM",NULL
,$3)); }
324 | HASHES body
{ $$
= doc_node_make
("(LISTBODY)",NULL
, doc_node_make_take_children
("ITEM",NULL
,$2)); }
327 tablerow: HASHES tablecells
{ $$
= doc_node_make_take_children
("TABROW",NULL
,$2); }
330 tablebody: tablebody tablerow
{ $$
= doc_node_add_child
($1,$2); }
331 | tablerow
{ $$
= doc_node_make
("(TABLEBODY)",NULL
,$1); }
334 tablecells: tablecells BARS optbody
{ $$
= doc_node_add_child
($1, doc_node_make_take_children
("TABCOL",NULL
,$3)); }
335 | optbody
{ $$
= doc_node_make
("(TABLECELLS)",NULL
, doc_node_make_take_children
("TABCOL",NULL
,$1)); }
338 defterms: defterms HASHES body
{ $$
= doc_node_add_child
($1,doc_node_make_take_children
("TERM",NULL
,$3)); }
339 | HASHES body
{ $$
= doc_node_make
("(TERMS)",NULL
,doc_node_make_take_children
("TERM",NULL
,$2)); }
342 deflistrow: defterms BARS optbody
344 $$
= doc_node_make_take_children
("DEFLISTITEM", NULL
, $1);
345 doc_node_add_child
($$
, doc_node_make_take_children
("DEFINITION", NULL
, $3));
349 deflistbody: deflistbody deflistrow
{ $$
= doc_node_add_child
($1,$2); }
350 | deflistrow
{ $$
= doc_node_make
("(DEFLISTBODY)",NULL
,$1); }
361 words: words anyword
{ $$
= strmerge
($1,$2); }
365 words2: words2 anywordurl
{ $$
= strmerge
($1,$2); }
378 | eol
{ $$
= strdup
("\n"); }
381 wordsnl: wordsnl anywordnl
{ $$
= strmerge
($1,$2); }
385 nocommawords: nocommawords TEXT
{ $$
= strmerge
($1,$2); }
386 | nocommawords URL
{ $$
= strmerge
($1,$2); }
391 commalist: commalist COMMA nocommawords
{ free
($2); $2=NULL
; $$
= doc_node_add_child
($1,doc_node_make
("STRING",$3,NULL
)); }
392 | nocommawords
{ $$
= doc_node_make
("(COMMALIST)",NULL
,doc_node_make
("STRING",$1,NULL
)); }
397 DocNode
* scdoc_parse_run
(int mode
) {
398 int modes
[] = {START_FULL
, START_PARTIAL
, START_METADATA
};
399 if
(mode
<0 || mode
>=sizeof
(modes
)) {
400 error("scdoc_parse_run(): unknown mode: %d\n",mode
);
402 scdoc_start_token
= modes
[mode
];
403 /* scdoc_start_token = START_FULL;
404 scdoc_metadata_mode = 0;
405 if(mode==SCDOC_PARSE_PARTIAL) {
406 scdoc_start_token = START_PARTIAL;
408 if(mode==SCDOC_PARSE_METADATA) {
409 scdoc_metadata_mode = 1;
412 method_type
= "METHOD";
413 if
(scdocparse
()!=0) {
419 void scdocerror
(const char *str
)
421 error("In %s:\n At line %d: %s\n\n",scdoc_current_file
,scdoclineno
,str
);
423 /* FIXME: this does not work well, since the reported linenumber is often *after* the actual error line
424 fseek(scdocin, 0, SEEK_SET);
427 while(line!=scdoclineno && !feof(scdocin)) {
428 int c = fgetc(scdocin);
431 txt = fgets(buf, 256, scdocin);
433 fprintf(stderr," %s\n-------------------\n", txt);