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 }
- This is Preform grammar, not regular C code.
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); } }
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;
- The structure symbol is private to this section.
<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 }; }
- This is Preform grammar, not regular C code.
§5.1. Kind already exists error5.1 =
kind *K = RP[1]; PRINT("Kind already exists: '%u'\n", K); ==> { fail }
- This code is used in §5 (twice).
kind *K = Kinds::new_base(syntax_tree, GET_RW(<declaration-line>, 1), K_value); Kinds::Behaviour::convert_to_unit(syntax_tree, K);
- This code is used in §5.
kind *K = Kinds::new_base(syntax_tree, GET_RW(<declaration-line>, 1), K_value); Kinds::Behaviour::convert_to_enumeration(syntax_tree, K);
- This code is used in §5.
§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;
- This code is used in §5.
§5.5. Symbol already exists error5.5 =
symbol *S = RP[1]; PRINT("Symbol already exists: '%W'\n", S->symbol_name); ==> { fail }
- This code is used in §5.
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;
- This code is used in §5.
symbol *S = RP[1]; kind *K = S->symbol_kind; Show result5.4.1;
- This code is used in §5.
int op = PLUS_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
int op = MINUS_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
int op = TIMES_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
int op = DIVIDE_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
int op = REMAINDER_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
int op = APPROXIMATION_OPERATION; Show arithmetic5.8.1;
- This code is used in §5.
§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;
int op = UNARY_MINUS_OPERATION; Show unary arithmetic5.14.1;
- This code is used in §5.
int op = ROOT_OPERATION; Show unary arithmetic5.14.1;
- This code is used in §5.
§5.16. Show real square root5.16 =
int op = REALROOT_OPERATION; Show unary arithmetic5.14.1;
- This code is used in §5.
int op = CUBEROOT_OPERATION; Show unary arithmetic5.14.1;
- This code is used in §5.
§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;
PRINT("'%W': %u\n", W, K);
§5.18. No such kind error5.18 =
PRINT("No such kind as '%W'\n", W); ==> { fail }
- This code is used in §5.
PRINT("Declaration not understood: '%W'\n", W); ==> { fail }
- This code is used in §5.