Add language definition document. Allow execution of codewords without parameter...
[robmyers:surgical_strike.git] / surgical_strike.y
1 /*
2     Surgical Strike (Free Software Version).
3     Copyright (C) 2008, 2014 Rob Myers
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 %{
20
21 #include <cstdio>
22 #include <cstring>
23 #include <string>
24
25 #include "surgical_strike.h"
26
27 #include "y.tab.hpp"
28
29 void yyerror(const char *);
30 int yyparse (void);
31 int yylex (void);
32
33 extern "C" int yywrap (void)
34 {
35     return 1;
36 }
37
38 #define YY_INPUT(buf,result,max_size)  {\
39     result = GetNextChar(buf, max_size); \
40     if ( result <= 0 ) \
41       result = YY_NULL; \
42     }
43
44 #define YYERROR_VERBOSE (1)
45
46 %}
47
48 %defines
49
50 %union
51  {
52    double floatnum;
53    char string[256];
54 }
55
56 %start program
57
58 %token INCOMING
59 %token CODEWORD
60 %token SET
61 %token MARK
62 %token CLEAR
63 %token MANOUVER
64 %token ROLL
65 %token SCALE
66 %token LOAD
67 %token CAMOUFLAGE
68 %token DELIVER
69
70 %token <floatnum> NUMBER
71 %token <string> STRING
72 %token <string> IDENTIFIER
73
74 %%
75
76 program: incoming statements;
77
78 incoming: INCOMING               { parse_incoming (); };
79
80 statements:
81 /* empty */
82 | statements statement;
83
84 statement:
85 codeword_definition
86 | command;
87
88 codeword_start: CODEWORD IDENTIFIER { parse_codeword ($2); };
89
90 codeword_end: SET                { parse_set (); };
91
92 codeword_definition: codeword_start commands codeword_end;
93
94 commands:
95 /* empty */
96 | commands command;
97
98 command:
99 MARK                             { parse_mark (); }
100 | CLEAR                          { parse_clear (); }
101 | MANOUVER NUMBER NUMBER NUMBER  { parse_manouver ($2, $3, $4); }
102 | ROLL NUMBER NUMBER NUMBER      { parse_roll ($2, $3, $4); }
103 | SCALE NUMBER NUMBER NUMBER     { parse_scale ($2, $3, $4); }
104 | LOAD STRING                    { parse_payload ($2); }
105 | CAMOUFLAGE STRING              { parse_camouflage ($2); }
106 | IDENTIFIER                     { parse_codeword_execution ($1, 1); }
107 | IDENTIFIER NUMBER              { parse_codeword_execution ($1, $2); }
108 | DELIVER                        { parse_deliver (); }
109 ;
110
111 %%
112
113 extern int yylineno;
114 extern char * yytext;
115
116 extern bool debug;
117
118 void yyerror (const char *msg)
119 {
120   std::fprintf (stderr, "%d: %s at '%s'\n", yylineno, msg, yytext);
121 }
122
123
124 int main(int argc, char ** argv)
125 {
126   std::string output_file = "out.obj";
127   if (((argc == 2) &&
128        (std::strcmp (argv[1], "--help") == 0)) ||
129       (argc > 3))
130   {
131       std::printf ("Surgical Strike Free Software version 0.4\n"
132                    "USAGE:\n"
133                    "surgical_strike - Read from stdin, write to out.obj|.mtl\n"
134                    "surgical_strike [input file] [output file] - "
135                    "Read input file, write output file\n");
136       exit (0);
137   }
138   if (debug) std::fprintf (stderr, "Starting up.\n");
139   if (argc == 2)
140   {
141       std::fprintf (stderr, "Opening input file %s.\n", argv[1]);
142       FILE * new_stdin = freopen (argv[1], "r", stdin);
143       if (new_stdin == NULL)
144       {
145           std::fprintf (stderr, "Couldn't open input file %s.\n", argv[1]);
146           exit (1);
147       }
148   }
149   if (argc == 3)
150   {
151       output_file = argv[2];
152   }
153   if (debug) std::fprintf (stderr, "Parsing input file.\n");
154   yyparse ();
155   if (debug) std::fprintf (stderr, "Executing commands.\n");
156   run_main (output_file);
157 }