A handful of bare minimum Preform syntax.
§1. Nonterminal names. This is a typical internal nonterminal being defined, though it's a bit more meta than most — it's a nonterminal which matches against the name of any nonterminal. (This is used only to parse inclusion requests for the debugging log.)
Note that we use the internal 1 to signal that a correct match must have exactly one word.
<preform-nonterminal> internal 1 { nonterminal *nt = Nonterminals::detect(Lexer::word(Wordings::first_wn(W))); if (nt) { ==> { -, nt }; return TRUE; } ==> { fail nonterminal }; }
§2. Text positions. A useful nonterminal which matches no text, but detects the position:
<if-start-of-paragraph> internal 0 { int w1 = Wordings::first_wn(W); if ((w1 == 0) || (compare_word(w1-1, PARBREAK_V))) return TRUE; ==> { fail nonterminal }; }
<if-not-cap> internal 0 { int w1 = Wordings::first_wn(W); if (Word::unexpectedly_upper_case(w1) == FALSE) return TRUE; ==> { fail nonterminal }; }
§4. Balancing. The following regular (not internal!) nonterminal matches any text in which braces and brackets are correctly paired.
<balanced-text> ::= ......
- This is Preform grammar, not regular C code.
§5. Inform contains relatively few syntaxes where commas are actually required, though they can optionally be used in many lists, as here:
parma ham, camembert, grapes
But for when we only want to spot comma placements, this can be used. Note that the comma matches only if not in brackets.
<list-comma-division> ::= ...... , ......
- This is Preform grammar, not regular C code.
§6. Literal numbers. (Inform itself doesn't use this, but has alternatives for cardinals and ordinals within the VM-representable range.)
<any-integer> internal 1 { if (Vocabulary::test_flags(Wordings::first_wn(W), NUMBER_MC)) { int N = Vocabulary::get_literal_number_value(Lexer::word(Wordings::first_wn(W))); ==> { N, - }; return TRUE; } ==> { fail nonterminal }; }
- This is Preform grammar, not regular C code.
§7. Literal text. Text is "with substitutions" if it contains square brackets, used in Inform for interpolations called "text substitutions".
<quoted-text> internal 1 { if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC+TEXTWITHSUBS_MC))) { ==> { Wordings::first_wn(W), - }; return TRUE; } ==> { fail nonterminal }; } <quoted-text-with-subs> internal 1 { if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXTWITHSUBS_MC))) { ==> { Wordings::first_wn(W), - }; return TRUE; } ==> { fail nonterminal }; } <quoted-text-without-subs> internal 1 { if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC))) { ==> { Wordings::first_wn(W), - }; return TRUE; } ==> { fail nonterminal }; }
- This is Preform grammar, not regular C code.
§8. For finicky technical reasons the easiest way to detect an empty piece of text "" is to provide a nonterminal matching it:
<empty-text> internal 1 { if ((Wordings::nonempty(W)) && (Word::compare_by_strcmp(Wordings::first_wn(W), U"\"\""))) { ==> { Wordings::first_wn(W), - }; return TRUE; } ==> { fail nonterminal }; }
- This is Preform grammar, not regular C code.