summaryrefslogtreecommitdiff
path: root/web/yacco2/grammar-testsuite/testout_prog.w
blob: 14491e43b4537e44c2896d0eb98eee242c7e402f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
@q file: testout_prog.w@>
@q%   Copyright Dave Bone 1998 - 2015@>
@q% /*@>
@q%    This Source Code Form is subject to the terms of the Mozilla Public@>
@q%    License, v. 2.0. If a copy of the MPL was not distributed with this@>
@q%    file, You can obtain one at http://mozilla.org/MPL/2.0/.@>
@q% */@>

@** Define variables.\fbreak
\ptindent{1) Holding file to start things off --- command line data is put into this file}
\ptindent{2) Define the \O2's tracing variable by macro}
\ptindent{3) \O2's token containers needed}
@<accrue testout code@>+=
#define Max_buf_size 2*1024
std::string Holding_file("testout_holding_file.cmd");
std::string To_parse_file;

YACCO2_define_trace_variables();
yacco2::TOKEN_GAGGLE JUNK_tokens;
yacco2::TOKEN_GAGGLE IP_tokens;
yacco2::TOKEN_GAGGLE Error_queue;

@** Local Routines.\fbreak
|GET_CMD_LINE| is a basic copy of |O2|'s command line routine.
It is changed as it just fetches the file to process. There are no other parameters to deal with.
Have a read and compare |O2|'s routine against this one to see the variances.
\O2's routines are written up in |common_externs.pdf| in the ``./docs'' folder.

|DUMP_ERROR_QUEUE| ditto's |O2|'s error processing routine.
Testout's difference to \O2{} is the use of its own error handler grammar.
This is due to the different T vocabulary defined over \O2's vocabulary.
This was done to show u what u'll be doing for your own compiler development
as your T vocabulary will definitely be different from \O2.
Have a look at the |testout_err_hdlr| grammar and see 
how it resolves the external file associated with the error T.
The Error T processing is basicly a template using your specific grammar
 relative to its own language/Terminal Vocabulary.

As O2's |o2_error_hdlr.lex| grammar  deals with its own specific errors,
this is why there is not a generic error template grammar that uses only the \ALLshift{}
to trace all the T errors as anonymous entities.
One could do this but u'll find that this is not too creative.
Look at |o2_error_hdlr.lex|'s subrule with tandom errors --- ``file-inclusion'' ``bad filename''
as an example.
   

Your own error reporting is open to your own code and style to format
 and notification.
 U might want to compare  |testout_terminals.T| and |testout_err_symbols.T|
 definitions against \O2's vocabulary: 
 |yacco2_terminals.T| and |yacco2_err_symbols.T| to get a feel on 
 the range of Tes within \O2. What they stand for, and the different
 definition templates used: canned to full \Cpp{} definition / implementation.


@*1 |GET_CMD_LINE| --- go fetch the fodder.\fbreak
To note: the ``File\_to\_parse'' parameter is passed in as a reference which
gets filled with the command line input.
The file's existence check is done and
if it exists, downstream parsing uses it passed in reference variable 
for the input tok\_can container
to parse its contents.

@<accrue testout code@>+=
void GET_CMD_LINE(int argc,char*argv[]@/
,const char*Holding@/
,std::string& File_to_parse@/
,yacco2::TOKEN_GAGGLE&Errors)
{
using namespace std;
using namespace NS_testout_err_symbols;
using namespace yacco2;
ofstream ofile;
ofile.open(Holding,ios_base::out|ios::trunc);
if(!ofile){
CAbs_lr1_sym*sym= new Err_bad_filename(Holding);
sym->set_external_file_id(1);
sym->set_line_no(1);
sym->set_pos_in_line(1);
Errors.push_back(*sym);
return;
}
if(argc==1){
char cmd_line[Max_buf_size];
cout<<"Please enter Command line to process: ";
cin.get(cmd_line,Max_buf_size,'\n');
ofile<<cmd_line;
File_to_parse+=cmd_line;
ofile.close();
}else{
for(int x= 1;x<argc;++x){
ofile<<argv[x];
File_to_parse+=argv[x];
}
ofile.close();
}
tok_can<std::ifstream> Cmd1_tokens(Holding);//sets the table of files controlled by yacco2 for parsing T gpsing
ifstream ifile;
ifile.open(File_to_parse.c_str());
if(!ifile){
CAbs_lr1_sym*sym= new Err_bad_filename(File_to_parse.c_str());
sym->set_external_file_id(1);
sym->set_line_no(1);
sym->set_pos_in_line(1);
Errors.push_back(*sym);
return;
}
ifile.close();
return;
}
@*1 |DUMP_ERROR_QUEUE| --- the teller of horror.\fbreak
The 2 |yacco2::PTR_LR1_eog__| added to the end-of-the-container allows 
the grammar's |start_rule| to be accepted.
@<accrue testout code@>+=
void DUMP_ERROR_QUEUE(yacco2::TOKEN_GAGGLE&Errors)
{
using namespace NS_yacco2_k_symbols;
using namespace yacco2;
Errors.push_back(*yacco2::PTR_LR1_eog__);
Errors.push_back(*yacco2::PTR_LR1_eog__);
using namespace NS_testout_err_hdlr;

Ctestout_err_hdlr fsm;
Parser pass_errors(fsm,&Errors,0);
pass_errors.parse();
yacco2::Parallel_threads_shutdown(pass_errors);
}

@** Mainline.\fbreak
The mainline code demonstrates various ways to do  ``literate programming:
a mixture of Literate programming code modules and standard ``c'' code.

{\bf{Note}:} I checked the returned code from the parser |Parser::erred|
as to whether a parse  error occurred.
This is the proper way to do things but u'll see my lazyness in \O2's program
listing to just check the ``Error queue''.
If u misused the |RSVP_FSM| macro from a monolithic grammar's |failed| directive to do this,
the parser did abort, the |failed| directive fired but the ``Error queue'' is empty as
the error T is placed within the ``Accept queue'' which is the context for a
threaded grammar to return a result back to a calling grammar.

To see that |failed| works within the monolithic context, use ``testout\_error.dat'' 
file as input.
\fbreak

{\bf{So be forwarned}}. I guess this should be checked for by \O2{}
and to thrown an error when compiling the grammar but for the moment it does not.
@<accrue testout code@>+=
int main(int argc, char* argv[])
{
  std::cout << "testout start" << std::endl;
using namespace yacco2;
@<turn on some \O2's tracing@>; 
@<get command line...@>; 
  using namespace NS_pager_1;
  tok_can<std::ifstream> cmd_line(To_parse_file.c_str());
  Cpager_1 pager_1_fsm;
  Parser testout_parse(pager_1_fsm,&cmd_line,&IP_tokens,0,&Error_queue,&JUNK_tokens,0);
  if (testout_parse.parse() == Parser::erred){
  std::cout << "===============>ERROR OCCURRED" << std::endl;
    @<if error queue not empty then deal with posted errors@>;
  }

exit:@/
std::cout << "Exiting testout" << std::endl;
  return 0;
}

@*1 Some Programming sections.
@*2 Turn on some of \O2's dynamic tracing variables.\fbreak
Tracings:\fbreak
\ptindent{T - terminals}
\ptindent{TH - threads if their fsm-debug options turned on}
\ptindent{MSG - messages between grammars}
\ptindent{MU - trace mutex  activity}
Notice that MU was turned off but kept as a comment.
Due to how |Cweb| deals with comments, the underscore ``\_'' must be escaped.
Have a look in the ``testout\_prog.w'' file where u'll see this.

You will not see any ``MSG'' or ``TH'' tracings as there was not a threaded grammar
called.
So why do u include them?
Just to pique your interest to \O2's delights.
@<turn on some \O2's tracing@>=
yacco2::YACCO2_T__ = 1;
yacco2::YACCO2_TH__ = 1;
yacco2::YACCO2_MSG__ = 1;
//yacco2::YACCO2\_MU\_TRACING\_\_ = 1;

@*2 Get command line, parse it, and place contents into a holding file.\fbreak
@<get command line, parse it, and place contents into a holding file@>=
  GET_CMD_LINE(argc,argv,Holding_file.c_str(),To_parse_file,Error_queue);
  @<if error queue not empty then deal with posted errors@>;


@*2 Do we have errors?.\fbreak
Check that error queue for those errors. 
Note, |DUMP_ERROR_QUEUE| will also flush out
 any launched threads for the good housekeeping or is it
housetrained seal
award? Trying to do my best in the realm of short lived winddowns.
@<if error queue not empty then deal with posted errors@>=
if(Error_queue.empty()!=true){
	DUMP_ERROR_QUEUE(Error_queue);
    return 1;
}


@*1 Testout implementation.\fbreak
Start the code output to |testout.cpp|
by appending its include file.
@(testout.cpp@>= 
@<accrue testout code@>;