]> ruin.nu Git - popboot.git/blob - parser.y
including iterator
[popboot.git] / parser.y
1
2 %{
3     #include <ctype.h>
4     #include <string>
5     #include <iostream>
6     #include <sstream>
7     #include <fstream>
8     #include <vector>
9         #include <cstdlib>
10
11     #include "action.h"
12         #include "planner.h"
13
14     using namespace std;
15
16     int yyparse(void);
17     int yylex (void);
18     void yyerror (char const *);
19
20     ifstream* input;
21     int line = 1;
22     vector<Action>* actions;
23     EffectsMap*     runlevels;
24 %}
25
26
27
28 %union {
29     Preconditions* preconds;
30     Literals* literals;
31     EffectsMap* effects;
32     string* str;   /* STR tokens */
33     int num;       /* NUM tokena */
34 }
35
36 %type <str> id
37 %type <preconds> preconds
38 %type <str> exec
39 %type <effects> effects
40 %type <literals> literals 
41 %token <str> STR 
42 %token <num> NUM
43
44 %left ','
45
46 %%
47
48 input   : runlvls '\n' actions 
49         ;
50
51
52 runlvls : '\n' runlvls
53         | effects                   { runlevels = $1; } 
54         ;
55
56 actions :  /* empty */
57         | actions action                 
58         | actions '\n'
59         ;
60
61
62 action  : id preconds '\n' exec effects '\n' {  
63     
64                                 actions->push_back( Action(*$1,*$2,*$4,*$5) ); 
65
66                                 //---------------------------------------------
67                                 // Debug test print :   
68 /*                              cerr << "id:  " << *$1 << endl;
69
70                                 // Precondition flags:
71                                 cerr << "a: " << (*$2)["a"] << endl;
72                                 cerr << "b: " << (*$2)["b"] << endl;
73                                 cerr << "c: " << (*$2)["c"] << endl;
74                                 cerr << "d: " << (*$2)["d"] << endl;
75                                 cerr << "e: " << (*$2)["e"] << endl;
76
77                                 cerr << "exe: " << *$4 << endl;
78
79                                 // Print number of effects
80                                 cerr << "0: " << (*$5)[0].size() << endl;
81                                 cerr << "99: " << (*$5)[99].size() << endl;
82                                 cerr << "88: " << (*$5)[88].size() << endl;
83
84                                 cerr << endl;
85 */                              //----------------------------------------------
86                                             }
87         ;
88
89
90
91
92 id      : STR '\n'                  { $$ = $1; }
93         ;
94
95 /* Preconditions (literals with flag) */
96 preconds: /* empty */               {   $$ = new Preconditions(); }
97         | preconds ','  preconds    {  
98                                         $$ = $1;
99                                         // $3 will only have on element
100                                         (*$$)[$3->begin()->first] =
101                                             $3->begin()->second;
102                                     }
103         | '?' STR                   {   
104                                         $$ = new Preconditions();
105                                         (*$$)[*$2] = false ;
106                                     } 
107         | STR                       {   
108                                         $$ = new Preconditions();
109                                         (*$$)[*$1] = true ;
110                                     }
111         ;
112
113 /* Executable */
114 exec    : STR '\n'                  { $$ = $1; }
115         ;
116
117 /* EffectMap */
118 effects : effects NUM ':' literals '\n' {
119                                         $$ = $1;
120                                         (*$$)[$2] = *$4;
121                                         }
122         | NUM ':' literals '\n'         {
123                                         $$ = new EffectsMap();
124                                         (*$$)[$1] = *$3 ;
125                                         }
126         ;
127
128
129 /* List of literals (effects) */
130 literals: literals ',' literals     { 
131                                         $$ = $1;
132                                         $$->push_back( *($3->begin()) ); 
133                                     }
134         | STR                       { 
135                                         $$ = new Literals();
136                                         $$->push_back(*$1); 
137                                     }
138         ;
139
140
141 %%
142
143 int 
144 yylex (void)
145 {
146     string str;
147
148     // Check for end of file
149     if ( input->eof() )
150         return 0;
151
152     // Ignore spaces
153     while ( input->peek()==' ' || input->peek()=='\t')
154         input->get();
155
156     // Ignore comments
157     while ( input->peek()=='#')
158         while ( input->peek()!='\n' )
159             input->get();
160
161
162
163
164     // Numbers
165     if ( isdigit(input->peek()) )
166     {
167         *input >> yylval.num;
168         return NUM;
169     }
170
171     // Alpha strings
172     if ( isalpha(input->peek()) )
173     {  
174         string* str = new string();
175         
176         int c = input->peek();
177         while (isalpha(c) || isdigit(c) || c=='_' || c=='.' )   
178         {
179             *str += input->get();
180             c = input->peek();
181         }
182         yylval.str = str;
183         return STR;
184     }
185
186     // String with spaces and other special characters
187     if ( input->peek()=='"' )
188     {
189         input->get();               // Consume "-character
190         string* str = new string();
191         while (input->peek()!='"')
192         {
193             *str += input->get();
194         }
195         input->get();               // Consume "-character
196
197         yylval.str = str;
198         return STR;
199     }
200
201     /* Return single char */
202     int c = input->get();          
203     if ( c=='\n' )
204         ++line;
205     return c;
206 }
207
208
209 void 
210 yyerror (char const *s)
211 {
212     cerr << "Line " << line << ": " << s << endl;
213 }
214
215 vector<string> stringToVector(string str){
216         vector<string> strings;
217
218         istringstream ist(str);
219         while (ist >> str){
220                 strings.push_back(str);
221         }
222
223         return strings;
224 }
225
226 int 
227 main (int argc, char** argv)
228 {
229
230     if (argc < 3)
231     {
232         cerr << "Syntax: " << argv[0] << 
233                 " <file> <runlevel> \"init state\"" << endl;
234         return 1;
235     }
236
237         Literals init = argc >= 4 ? stringToVector(argv[3]) : Literals();
238     ifstream file(argv[1]);
239     if (!file)
240     {
241         cerr << "Unable to open file: " << argv[1] << endl;
242         exit(2);
243     }
244
245     // Set global variables
246     input = &file;
247     actions = new vector<Action>();
248     runlevels = new EffectsMap();
249
250     yyparse();
251
252 /*    cerr << (*runlevels)[2].size() << endl;
253     cerr << (*runlevels)[3].size() << endl;
254     cerr << (*runlevels)[4].size() << endl;
255     cerr << (*runlevels)[5].size() << endl;
256 */
257     Planner p(*actions, init, (*runlevels)[atoi(argv[2])]);
258     p.execute();
259
260     delete actions;
261         delete runlevels;
262 }