struct token_config config;
char *file_name;
int parse_error;
+ struct exec *prog;
## parse context
};
},
};
int doprint=0, dotrace=0, doexec=1, brackets=0;
- struct exec **prog;
int opt;
while ((opt = getopt_long(argc, argv, options, long_options, NULL))
!= -1) {
break;
}
if (ss)
- prog = parse_oceani(ss->code, &context.config,
- dotrace ? stderr : NULL);
+ parse_oceani(ss->code, &context.config,
+ dotrace ? stderr : NULL);
else {
fprintf(stderr, "oceani: cannot find section %s\n",
section);
exit(1);
}
} else
- prog = parse_oceani(s->code, &context.config,
- dotrace ? stderr : NULL);
- if (!prog) {
- fprintf(stderr, "oceani: fatal parser error.\n");
+ parse_oceani(s->code, &context.config,
+ dotrace ? stderr : NULL);
+ if (!context.prog) {
+ fprintf(stderr, "oceani: no program found.\n");
context.parse_error = 1;
}
- if (prog && doprint)
- print_exec(*prog, 0, brackets);
- if (prog && doexec && !context.parse_error) {
- if (!analyse_prog(*prog, &context)) {
+ if (context.prog && doprint)
+ print_exec(context.prog, 0, brackets);
+ if (context.prog && doexec && !context.parse_error) {
+ if (!analyse_prog(context.prog, &context)) {
fprintf(stderr, "oceani: type error in program - not running.\n");
exit(1);
}
- interp_prog(*prog, argv+optind+1);
+ interp_prog(context.prog, argv+optind+1);
}
- if (prog) {
- free_exec(*prog);
- free(prog);
+ if (context.prog) {
+ free_exec(context.prog);
}
while (s) {
struct section *t = s->next;
break;
}
+### Top level structure
+
+All the language elements so far can be used in various places. Now
+it is time to clarify what those places are.
+
+At the top level of a file there will be a number of declarations.
+Many of the things that can be declared haven't been described yet,
+such as functions, procedures, imports, named types, and probably
+more.
+For now there are two sorts of things that can appear at the top
+level. They are predefined constants and the main program. While the
+syntax will allow the main program to appear multiple times, that will
+trigger an error if it is actually attempted.
+
+The various declarations do not return anything. They store the
+various declarations in the parse context.
+
+###### Parser: grammar
+
+ $void
+ Ocean -> DeclarationList
+
+ DeclarationList -> Declaration
+ | DeclarationList Declaration
+
+ Declaration -> DeclareConstant
+ | DeclareProgram
+ | NEWLINE
+
+ ## top level grammar
+
### Finally the whole program.
Somewhat reminiscent of Pascal a (current) Ocean program starts with
the keyword "program" and a list of variable names which are assigned
values from command line arguments. Following this is a `block` which
-is the code to execute.
+is the code to execute. Unlike Pascal, constants and other
+declarations come *before* the program.
As this is the top level, several things are handled a bit
differently.
###### Binode types
Program,
-###### Parser: grammar
+###### top level grammar
+
+ DeclareProgram -> Program ${ {
+ struct parse_context *c = config2context(config);
+ if (c->prog)
+ type_err(c, "Program defined a second time",
+ $1, NULL, 0, NULL);
+ else
+ c->prog = $<1;
+ } }$
+
$*binode
Program -> program OpenScope Varlist Block OptNL ${