Reading declarations from a file.


§1. Keeping the syntax module happy. We are going to need to use the sentence-breaking apparatus from the syntax module, which means that the following four nonterminals need to exist. But in fact they are really just placeholders — they are wired so that they can never match any text.

<dividing-sentence> ::=
    ... ==> { fail }

<structural-sentence> ::=
    ... ==> { fail }

<language-modifying-sentence> ::=
    ... ==> { fail }

<comma-divisible-sentence> ::=
    ... ==> { fail }

§2. Loading kinds.

void Declarations::load_kinds(text_stream *arg) {
    filename *F = Filenames::from_text(arg);
    TextFiles::read(F, FALSE, "unable to read kinds file", TRUE,
        &Declarations::load_kinds_helper, NULL, NULL);
}

void Declarations::load_kinds_helper(text_stream *text, text_file_position *tfp, void *state) {
    if ((Str::get_first_char(text) == '!') ||
        (Str::get_first_char(text) == 0)) return;  skip blanks and comments
    Kinds::Interpreter::despatch_kind_command(NULL, text);
}

§3. Loading from a file. The following function reads a file whose name is in arg, feeds it into the lexer, builds a syntax tree of its sentences, and then walks through that tree, applying the Preform nonterminal <declaration-line> to each sentence.

parse_node_tree *syntax_tree = NULL;
void Declarations::load_from_file(text_stream *arg) {
    filename *F = Filenames::from_text(arg);
    feed_t FD = Feeds::begin();
    source_file *sf = TextFromFiles::feed_into_lexer(F, NULL_GENERAL_POINTER);
    wording W = Feeds::end(FD);
    if (sf == NULL) { PRINT("File has failed to open\n"); return; }
    syntax_tree = SyntaxTree::new();
    Sentences::break(syntax_tree, W);
    SyntaxTree::traverse(syntax_tree, Declarations::parse);
}

void Declarations::parse(parse_node *p) {
    if (Node::get_type(p) == SENTENCE_NT) {
        wording W = Node::get_text(p);
        <declaration-line>(W);
    }
}

§4.

enum symbol_CLASS
define SYMBOL_MC 0x80
define EXACT_PARSING_BITMAP
    (SYMBOL_MC + KIND_SLOW_MC)
DECLARE_CLASS(symbol)

typedef struct symbol {
    wording symbol_name;
    kind *symbol_kind;
    CLASS_DEFINITION
} symbol;

§5.

<declaration-line> ::=
    new unit <k-kind> |                                   ==> Kind already exists error5.1
    new unit ... |                                        ==> Create new unit5.2
    new enum <k-kind> |                                   ==> Kind already exists error5.1
    new enum ... |                                        ==> Create new enum5.3
    <k-kind> * <k-kind> = <k-kind> |                      ==> New arithmetic rule5.4
    <existing-symbol> = ... |                             ==> Symbol already exists error5.5
    ... = <existing-kind> |                               ==> Create symbol5.6
    <existing-symbol> + <existing-symbol> |               ==> Show plus5.8
    <existing-symbol> - <existing-symbol> |               ==> Show minus5.9
    <existing-symbol> * <existing-symbol> |               ==> Show times5.10
    <existing-symbol> over <existing-symbol> |            ==> Show divide5.11
    <existing-symbol> % <existing-symbol> |               ==> Show remainder5.12
    <existing-symbol> to the nearest <existing-symbol> |  ==> Show approx5.13
    - <existing-symbol> |                                 ==> Show unary minus5.14
    square root of <existing-symbol> |                    ==> Show square root5.15
    real square root of <existing-symbol> |               ==> Show real square root5.16
    cube root of <existing-symbol> |                      ==> Show cube root5.17
    <existing-symbol> |                                   ==> Show symbol5.7
    ... which varies |                                    ==> { -, - }
    ...                                                   ==> Fail with error5.19

<existing-kind> ::=
    <k-kind> |  ==> { pass 1 }
    ...         ==> No such kind error5.18;

<existing-symbol> internal {
    parse_node *results = Lexicon::retrieve(SYMBOL_MC, W);
    if (results) {
        symbol *S = RETRIEVE_POINTER_symbol(Lexicon::get_data(Node::get_meaning(results)));
        if (S) { ==> { -, S }; return TRUE; }
    }
    ==> { fail nonterminal };
}

§5.1. Kind already exists error5.1 =

    kind *K = RP[1];
    PRINT("Kind already exists: '%u'\n", K);
    ==> { fail }

§5.2. Create new unit5.2 =

    kind *K = Kinds::new_base(syntax_tree, GET_RW(<declaration-line>, 1), K_value);
    Kinds::Behaviour::convert_to_unit(syntax_tree, K);

§5.3. Create new enum5.3 =

    kind *K = Kinds::new_base(syntax_tree, GET_RW(<declaration-line>, 1), K_value);
    Kinds::Behaviour::convert_to_enumeration(syntax_tree, K);

§5.4. New arithmetic rule5.4 =

    kind *K1 = (kind *) RP[1];
    kind *K2 = (kind *) RP[2];
    kind *K = (kind *) RP[3];
    Kinds::Dimensions::make_unit_derivation(K1, K2, K);
    Show result5.4.1;

§5.5. Symbol already exists error5.5 =

    symbol *S = RP[1];
    PRINT("Symbol already exists: '%W'\n", S->symbol_name);
    ==> { fail }

§5.6. Create symbol5.6 =

    kind *K = RP[1];
    symbol *S = CREATE(symbol);
    S->symbol_name = GET_RW(<declaration-line>, 1);
    S->symbol_kind = K;
    Lexicon::register(SYMBOL_MC, S->symbol_name, STORE_POINTER_symbol(S));
    Show result5.4.1;

§5.7. Show symbol5.7 =

    symbol *S = RP[1];
    kind *K = S->symbol_kind;
    Show result5.4.1;

§5.8. Show plus5.8 =

    int op = PLUS_OPERATION;
    Show arithmetic5.8.1;

§5.9. Show minus5.9 =

    int op = MINUS_OPERATION;
    Show arithmetic5.8.1;

§5.10. Show times5.10 =

    int op = TIMES_OPERATION;
    Show arithmetic5.8.1;

§5.11. Show divide5.11 =

    int op = DIVIDE_OPERATION;
    Show arithmetic5.8.1;

§5.12. Show remainder5.12 =

    int op = REMAINDER_OPERATION;
    Show arithmetic5.8.1;

§5.13. Show approx5.13 =

    int op = APPROXIMATION_OPERATION;
    Show arithmetic5.8.1;

§5.8.1. Show arithmetic5.8.1 =

    symbol *S1 = RP[1];
    symbol *S2 = RP[2];
    kind *K = Kinds::Dimensions::arithmetic_on_kinds(S1->symbol_kind, S2->symbol_kind, op);
    Show result5.4.1;

§5.14. Show unary minus5.14 =

    int op = UNARY_MINUS_OPERATION;
    Show unary arithmetic5.14.1;

§5.15. Show square root5.15 =

    int op = ROOT_OPERATION;
    Show unary arithmetic5.14.1;

§5.16. Show real square root5.16 =

    int op = REALROOT_OPERATION;
    Show unary arithmetic5.14.1;

§5.17. Show cube root5.17 =

    int op = CUBEROOT_OPERATION;
    Show unary arithmetic5.14.1;

§5.14.1. Show unary arithmetic5.14.1 =

    symbol *S1 = RP[1];
    kind *K = Kinds::Dimensions::arithmetic_on_kinds(S1->symbol_kind, NULL, op);
    Show result5.4.1;

§5.4.1. Show result5.4.1 =

    PRINT("'%W': %u\n", W, K);

§5.18. No such kind error5.18 =

    PRINT("No such kind as '%W'\n", W);
    ==> { fail }

§5.19. Fail with error5.19 =

    PRINT("Declaration not understood: '%W'\n", W);
    ==> { fail }