No previous Up Next

Main program
(main)

This document describes the body of the program which calls all the other procedures.

1 Outline of the program

The program is divided into five main passes. The first pass is preceded by initialization (section 2), and the last pass is followed by finalization (section 8). All the passes may not be executed in all cases—for example, if a pass fails, or if the user elects not to proceed, then the following passes will be skipped.

In the first pass the input file is scanned and parsed. During parsing type checking is performed, see section 3

The second pass is entered on request by the user. In this pass the global semantic restrictions are tested. These apply to the definition of the rules (section 4.1) and the attribute declarations (section 4.2). The restrictions on the attribute assignments are tested when these are internally transformed (section 4.3). These transformed attribute assignments are used in the fifth pass.

In the third pass it is first checked whether the abstract tree grammar, as described in the input, can be implemented according to the flat implementation method. If this is possible the dependency graph is generated. During the generation it is possible that the number of attribute-element pairs exceeds the limit set by the current implementation. When this happens the rest of the passes are aborted. See section 5

In the fourth pass the Simple Multi-Pass algorithm is applied to the dependency graph. If there exists more than one solution, the best solution is chosen. See section 6

The fifth pass is entered on request by the user. In this pass the Pascal object program is generated using the SMP-solution. This program evaluates the attributes according to the attribute assignments. See section 7

We present an outline of the program, according to the above description:

In the following sections we describe each of the five passes, as well as the initialization and finalization.

The procedure add screen info [screen 2.1.3] is used to update the current pass name displayed on the terminal. The procedure write elapsed time [screen 2.1.2] is used to update the elapsed run time as displayed by the screen module.

2 Initialization phase

In the initialization phase a number of modules used by the main program are initialized. The following modules are initialized : the screen module (by calling the procedure initialize screen [screen 2.1.1]), the error module (procedure init errors [errors 1]), the binary tree module (procedure init tree [bintree 3.1]) and the performance analysis module (procedure perf init [perform 1]).

3 First pass: lexical en syntactic analysis

In the first pass the entire input is read [scanner] and checked (parsed) for grammatical correctness [parser]. During the parsing a number of type checks are performed, and errors are written to a listing file [listing]. The input is stored in the binary tree [bintree].

This pass is divided into a number of smaller parts which will be described in the following sub-sections.

3.1 Initialization

Before the input is read, the procedure open scanner input file asks for an input filename [openfiles].

The user is asked whether he wants the screen module to operate in trace mode or in fast mode, which is signaled to the screen module by the procedure inform screen [screen 2.1.4].

The listing and scanner module are initialized by calling the procedures init listing [listing 1] and init scanner [scanner 1]. The listing module has to be initialized before the scanner module, because the scanner directly outputs the first line of the input file to the listing module. The listing module cannot be initialized earlier because the input filename is used in the heading on each page of the listing.

3.2 Reading the input

This is done by calling the parser procedure from the parser module. Before this is done, however, the procedure init level stack [screen 2.2.1] is called to display the level stack on the screen of the terminal.

3.3 Finalization

After the entire input has been read a summary of the number of errors is printed in the listing by the procedure fin errors [errors 1] and the level stack is removed by calling the procedure purge level stack [screen 2.2.2].

4 Second pass: semantical analysis

As we saw in the outline of the program, the second pass is subdivided into three main parts. These parts test the grammar, calculate the attribute relations, and transform the attribute assignments, during which the visibility and consistency of these are tested. If serious errors are found, then they are reported and the rest of the passes are skipped. The three parts are described in the following subsections.

4.1 Testing the grammar

In this subsection we describe the tests that involve the global properties of the grammar read by the first pass. The subdivision of this part is:

4.2 Calculating the attributes

In this part the attribute relations that make use of the class rules are calculated and are simultaneously checked for correctness. This is done by the procedure gen all attributes [pass2 5].

4.3 Testing and transforming the semantic rules

In the first pass the semantic rules were tested using a number of local typing constraints. In this part of the second pass all other checks are performed. The most complicated test is the consistency test. To perform this test the entire set of attribute assignments are being rearranged. During this transformation process the visibility of the attributes is checked by making use of the class rules. This is done by the procedure transform [trans 1], which is called with the value of the variable with tracing, whose value is determined by the options [parser 2].

The parameter trans errors contains the number of errors found during the transformation process. If errors are found the following passes will not be executed.

5 Third pass: generation of the dependency graph

The third pass tests whether the given grammar can be implemented according to the flat implementation method. This test is performed by the function flatimplementable [depend 1]. If this is not possible the dependency graph will not be generated and also the rest of the passes will be skipped. If the grammar is flat implementable, the dependency graph is generated by the procedure generate all dependencies [depend 4]. If there are more attribute-element pairs than can be represented in this implementation, the generated graph cannot be represented correctly, and the rest of the passes are aborted.

6 Fourth pass: simple multi-pass algorithm

In this pass the Simple Multi-Pass algorithm is applied to the dependency graph generated by the previous pass. This is done by calling the function smp algorithm [allsmp 3], which returns TRUE whenever a solution is found, otherwise FALSE. The solution, if found, is represented by the variables partition, part dir, one pass and passes, which are given to the function as parameters.

7 Fifth pass: generation of the evaluator

In this last pass the actual evaluator is generated if the user requests it. The generation is based on the input grammar and the best Simple Multi-Pass solution that has been found in the previous pass. The generation is done by calling the procedure gen program [genera 1].

8 Finalization phase

In this phase the program asks the user what information he wants in the listing file. These questions can be structured in the following way:

The procedure print tree [printtree 1] prints the contents of the binary tree. The procedure perf print [perform 1] prints the performance statistics.

9 Interface

This module uses declarations from the following modules:

In the following subsections we will give a list of imported declarations listed by module.

Screen management module (screen))

Global definitions module (definitions)

Performance module (perform)

The listing generator (listing)

The error handler module (errors)

The scanner module (scanner)

The binary identifier tree module (bintree)

The parser module (parser)

The print binary identifier tree module (printtree)

The attribute assignment transformation module (trans)

The simple multi-pass module (allsmp)

The dependency graph generation module (depend)

The second pass module (pass2)

The program generation module (generator)

10 Listing

[INHERIT ('definitions.pen',
          '[-.screen]openfiles.pen',
          'perform.pen',
          'listing.pen',
          '[-.screen]screen.pen',
          'errors.pen',
          'scanner.pen',
          'bintree.pen',
          'parser.pen',
          'printtree.pen',
          'trans.pen',
          'allsmp.pen',
          'depend.pen',
          'pass2.pen',
          'generator.pen')]

PROGRAM parsergenerator(output);


VAR
  msg          : VARYING[80] OF char;

(* the smp-solution *)
  partition : tpartition;
  part_dir  : tpart_dir;
  one_pass  : tset_node;
  passes    : integer;



(*      PROCEDURES                                                            *)

  FUNCTION ask_yes_or_no (question: t_question) : boolean;
  (* This procedure asks the question and returns TRUE if a Y is given      *)
  (* and FALSE if a N is given and repeats its question in every other case *)
  VAR answer : char;
      ok     : boolean;
  BEGIN
     REPEAT
       write_screen( question + ' (y/n) ');
       readln(answer);
       writecr_screen;
       ok := answer IN ['Y','y','J','j','N','n'];
       IF   NOT ok
       THEN writeln_screen('answer "y" or "n" ');
     UNTIL ok;
     ask_yes_or_no := answer IN ['Y','y','J','j']
  END;

  FUNCTION user_request(question : VARYING[l] OF char; test : boolean) : boolean;
  BEGIN
    IF   test
    THEN user_request := TRUE
    ELSE IF   ask
         THEN user_request := ask_yes_or_no(question)
         ELSE user_request := FALSE
  END;

10.1 Initialization

BEGIN

  initialize_screen(' AAPT-generator ',ask_yes_or_no('vt100 '));
  wait(0.5);
  init_errors;
  init_tree;
  perf_init;

10.2 Pass one: scanning and parsing

  add_screen_info('Pass 1 : Scanning and parsing');
  open_scanner_input_file;
  writeln_screen;
  inform_screen(ask_yes_or_no('tracing '));
  with_scan_echo := ask_yes_or_no('show scanning ');
  init_listing;
  init_scanner;
  init_level_stack;
  parser;
  writeln_screen;
  writeln_screen;
  fin_errors;
  purge_level_stack;
  add_screen_info('Pass 2 : Semantic checks and transformation');
  IF   ask_yes_or_no('pass2 ') THEN

10.3 Pass two: semantic chechs and transformation

  BEGIN
    print_page;
    write_elapsed_time;
    inform_screen(ask_yes_or_no('tracing '));
    init_level_stack;                           perf_start_time(perf_2_cl);
    test_all_classes_defined;
    write_elapsed_time;
    test_deterministic;                         perf_end_time  (perf_2_cl);
    write_elapsed_time;                         perf_start_time(perf_2_reach);
    test_reachability(r_conc);
    test_reachability(r_comp);                  perf_end_time  (perf_2_reach);
    write_elapsed_time;                         perf_start_time(perf_2_term);
    test_termination;                           perf_end_time  (perf_2_term);
    write_elapsed_time;                         perf_start_time(perf_2_attr);
    gen_all_attributes;                         perf_end_time  (perf_2_attr);
    write_elapsed_time;
    transform(trans_errors, with_tracing);
    write_elapsed_time;
    purge_level_stack;
    IF   trans_errors > 0
    THEN BEGIN
           print_newline;
           writev(msg,'MESSAGE: total number of transformation error(s) :',
                      trans_errors : 4);
           writeln_screen(msg);
           write(listing, msg);
           print_newline;
           writev(msg,'WARNING: dependency generation surpressed');
           writeln_screen(msg);
           write(listing, msg);
           print_newline
         END
    ELSE
    IF   NOT   flatimplementable
    THEN BEGIN
           print_newline(2);
           write(listing, 'NO FLAT IMPLEMENTATION');
           print_newline;
           writev(msg, 'WARNING: no flat implementation');
           writeln_screen(msg);
           write(listing, msg);
           print_newline
         END
    ELSE

10.4 Pass three: generate dependency graph

  BEGIN
    add_screen_info('Pass 3 : Generate dependency graph');
    print_page;
    write(listing, 'FLAT IMPLEMENTATION');
    print_newline(2);
    with_dep_info := ask_yes_or_no('dependency info ');
    inform_screen(ask_yes_or_no('tracing '));
    init_level_stack;
    write_elapsed_time;
    IF   NOT generate_all_dependencies
    THEN BEGIN
           writev(msg, 'ERROR: too many pairs for this implementation');
           writeln_screen(msg);
           write(listing, msg);
           print_newline;
           purge_level_stack
         END
    ELSE

10.5 Pass four: find simple multi-pass solution

  BEGIN
    purge_level_stack;
    add_screen_info('Pass 4 : Find simple multi-pass solution');
    IF   NOT smp_algorithm(partition, part_dir, one_pass, passes)
    THEN BEGIN
           writev(msg, 'ERROR: no Simple Multi-Pass Solution possible');
           writeln_screen(msg);
           write(listing, msg);
           print_newline
         END
    ELSE

10.6 Pass five: pascal program generation

  BEGIN
    add_screen_info('Pass 5 : PASCAL program generation');
    IF   ask_yes_or_no('generate pascal program ')
    THEN BEGIN
           inform_screen(ask_yes_or_no('tracing '));
           with_gen_echo := ask_yes_or_no('show generation ');
           init_level_stack;
           gen_program(partition, part_dir, one_pass, passes);
           purge_level_stack
         END;

  END (* pass five *)
  END (* pass four *)
  END (* pass tree *)
  END; (* pass two *)

10.7 Finals

  add_screen_info('Finals');
  IF   user_request('names ', with_names)
  THEN BEGIN
         with_all_names := user_request('all names ', with_all_names);
         print_tree
       END;
  IF   user_request('statistics ',with_statistics)
  THEN perf_print(listing);
  write_elapsed_time;
  finalize_screen
END.


My life as a hacker | My home page