.PAGE SIZE 60, 68 .RIGHT MARGIN 68 .LAYOUT 1, 2 .NO FLAGS ACCEPT .NO FLAGS OVERSTRIKE .NO FLAGS SUBSTITUTE .FLAGS BOLD .TITLE LT012: Practical LSE Language Templates .SUBTITLE B.#Z.#Lederman WU#World Communications, New York .CENTER ^*LT012: ^&Practical LSE Language Templates\&\* .BLANK 2 .CENTER Tuesday October 18, 1988 .BLANK .CENTER 5:00 p.m. - 6:00 p.m. South Hall Anaheim Marriott .BLANK 2 .CENTER ^*B.#Z.#Lederman\* .BLANK .CENTER WU World Communications .CENTER New York, NY 10004-2464 .BLANK .NOTE ^*Abstract\* This session takes a pragmatic approach to defining language templates, particularly for "languages" which have not been formally defined. Sample language templates will be shown (particularly a template for RUNOFF), and will show how some VMS utilities may be used to help with the definitions. .BLANK Some experience with LSE (to the extent of knowing what the product is, and how it is used) is assumed for this session, but it's not necessary to have written a template. .END NOTE .BLANK 2 .CENTER ^*Starting out.\* .PARAGRAPH In the documentation for LSE, and in other sessions I have seen, the first step they give for defining a template is to formally define the language, usually in BNF (Backus-Naur Form) language. This is fine if such a definition exists: if not, then a lot of time could be spent trying to create such a definition. In many cases I believe such a definition is not needed, and have gone ahead and created templates without such a definition. What is needed is a complete definition or listing of the language so it's elements (commands, verbs, instructions, qualifiers, etc.) are known, and some decisions must be made about the targeted use for the template. .PARAGRAPH A definition of the desired language generally is available through the documentation for that language. Example#1 (shown at the end of this paper) is pages 2 and 3 from the ^&VAX DSR Quick Reference Guide\&, a brief reference for RUNOFF. Example#2 is page 9-8 from the ^&VAX MACRO and Instruction Set Reference Manual\&. Both of these documents give a perfectly adequate definition of their respective documents for the purpose of defining an LSE template: in fact, they are laid out quite well for the first stage of definition. .PARAGRAPH Something else which helps is to have a template for the LSE definition language itself. When I did my definitions one was not supplied with LSE, so I made up my own. This was not a complete definition: it was just enough to simplify entering the LSE definitions. Even though a language definition for LSE is now supplied with LSE, I still believe my definitions are useful for entering large numbers of definitions. I really only defined two tokens: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 23 DEFINE TOKEN placeholder - /LANGUAGE=LSE - /DESCRIPTION="Define a place holder" - /TOPIC="DEFINE PLACEHOLDER" .BLANK "DEFINE PLACEHOLDER {placeholder_name} -" " /LANGUAGE=MACRO32 -" ! NOTE HARD CODED LANGUAGE ! " /NOAUTO_SUBSTITUTE - " " /DESCRIPTION=""[placeholder_description]"" -" " /DUPLICATION=CONTEXT_DEPENDENT -" " /SEPARATOR="" ""-" " /TOPIC=""[help_topic]""-" " /TYPE=TERMINAL -" " /LEADING="" ""-" " /TRAILING="" """ "" " ""{placeholder_body}"" " "" "END DEFINE" "" .BLANK END DEFINE .BLANK.TEST PAGE 17 DEFINE TOKEN token - /LANGUAGE=LSE - /DESCRIPTION="Define a Token" - /TOPIC="DEFINE TOKEN" .BLANK "DEFINE TOKEN {token_name} -" " /LANGUAGE=MACRO32 -" ! NOTE HARD CODED LANGUAGE ! " /DESCRIPTION=""[token_description]"" -" " /TOPIC=""[help_topic]"" " "" " ""{token_body}"" " "" "END DEFINE" "" .BLANK END DEFINE .BLANK.JUSTIFY.FILL followed by definitions of the placeholders such as {token_name}, etc. The reason for this is that a lot of text has to be entered manually, and it saved a lot of time to be able to type "tok" and Control-E to expand out a token, then type Control-N to skip to the next place that needed text entered. The definitions supplied now with LSE are more complete, but also give a lot more options and have to pass through more menus to create a new blank token or placeholder definition. By using fixed templates designed just for the purpose of text entry, much time and effort is saved. .PARAGRAPH Notice in my definitions that I "hard coded" the language being defined, in this case Macro-32. This saves typing the language in over and over again (and in some cases forgetting to type it in), but the definition has to be changed for each new language defined, or separate templates can be used. .BLANK 2.TEST PAGE 5 .CENTER ^*DEFINE LANGUAGE definition.\* .PARAGRAPH The first thing LSE wants to see is the definition of the language itself. Most of the definitions here are reasonably straight-forward. .BLANK.NO JUSTIFY.NO FILL DEFINE LANGUAGE RUNOFF - /COMMENT=( - NOBEGIN, - NOEND, - NOFIXED, - NOLINE, - TRAILING=(".COMMENT",".!")) - /CAPABILITIES=NODIAGNOSTICS - /COMPILE_COMMAND="RUNOFF" - /EXPAND_CASE=AS_IS - /FILE_TYPES=(.RNO,.RNB,.RNC,.RND,.RNE,.RNH,.RNL,.RNM,.RNS) - /HELP_LIBRARY=user$device:[lederman.lse]rno.hlb - /IDENTIFIER_CHARACTERS= - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - /INITIAL_STRING=".COMMENT [document_name]" - /LEFT_MARGIN=1 - /PLACEHOLDER_DELIMITERS=( - REQUIRED= ("{","}"), - REQUIRED_LIST= ("{","}..."), - OPTIONAL= ("[","]"), - OPTIONAL_LIST= ("[","]...")) - /PUNCTUATION_CHARACTERS=".,:;!?()""'" - /NOQUOTED_ITEM - /RIGHT_MARGIN=78 - /TAB_INCREMENT=8 - /TOPIC_STRING="rno" - /VERSION="BZL-V1.4" - /WRAP .BLANK.JUSTIFY.FILL.TEST PAGE 3 Some of the items are not entirely obvious. First, if you have a language where a character starts a comment (as the command ".COMMENT" starts a comment in RUNOFF), it is actually specified as a TRAILING comment (I gather this means the comment trails the indicator). Some other languages like "C" have to have markers before and after comments, hence the other options. The best guide I can give for this is to look at the DEC supplied language definitions for examples of comment string definitions. .BLANK.TEST PAGE 3 "/CAPABILITIES" is for compilers which return information on errors (the line number, etc.). This is very handy, but most third party compilers, and utilities like RUNOFF, don't do this. If you are supporting your own compiler, look seriously at this. DEC recently added an "ASCII text only" version of the way the compiler passes information back to LSE, which makes this option much easier to implement. It's very nice to have the compiler point the user back to the line in error while still in the editor. .BLANK.TEST PAGE 3 "/EXPAND_CASE" allows you to force upper or lower case if the language requires it (or if you want to force your own convention). .BLANK.TEST PAGE 3 "/FILE_TYPES" specifies the file extension which LSE will recognize as signifying a particular language definition. This is very handy, as the user doesn't have to manually specific the language: LSE will recognize ".FOR" as FORTRAN, ".COB" as COBOL, ".B32" as BLISS, etc. I got my list of extensions out of the RUNOFF documentation, and simply entered all of the same extensions that the RUNOFF utility recognizes as normal text input files. .BLANK "/IDENTIFIER_CHARACTERS" is usually the alphabet and numerals. .BLANK.TEST PAGE 3 "/PUNCTUATION_CHARACTERS" are usually the characters you want LSE to identify as punctuation: this will cause it to stop on these characters and use them to separate words. .BLANK.TEST PAGE 3 "/LEFT_MARGIN", "/RIGHT_MARGIN", "/TAB_INCREMENT", and "/WRAP" allow you to set the default layout format for the entry of text. This shows another of the advantages of using LSE: the ability to help enforce coding standards. In this case, RUNOFF is primarily used for formatting text, so I'm not doing anything fancy. .BLANK.TEST PAGE 3 "/INITIAL_STRING" allows inserting text at the beginning of a new, blank file. This is another way to help set a standard, as you can point to a placeholder which defines an entire program (or module) header. .BLANK.TEST PAGE 3 "/PLACEHOLDER_DELIMITERS" are important: they tell the editor how to define placeholder identifiers, which placeholders are optional, and which are mandatory. LSE will try not to let you leave out a required placeholder. If the language manual or guide uses a particular convention to mark placeholders, try to follow it so that users will see the same thing in the manuals as in the editor. The convention shown above where curly brackets are for required placeholders and square brackets are for optional placeholders is a common one in DEC languages and manuals. .BLANK.TEST PAGE 3 There are cases where a bracket itself cannot be used to delimit a placeholder, because it means something in the language itself. In this case, a two character combination which doesn't have a meaning in that language is used. A combination used by a number of DEC languages which I also used for my MACRO definition is: .BLANK.TEST PAGE 6 #####/PLACEHOLDER_DELIMITERS=( - .BREAK ########REQUIRED= ("{~","~}"), - .BREAK ########REQUIRED_LIST= ("{~","~}..."), - .BREAK ########OPTIONAL= ("[~","~]"), - .BREAK ########OPTIONAL_LIST= ("[~","~]...")) - .BLANK 2.TEST PAGE 3 "/TOPIC_STRING" is used to specify a prefix in a help file (a level 1 entry in a help file) when "HELP LANGUAGE" is invoked within LSE. It's added to the "/TOPIC" string on each token and placeholder definition. .BLANK.TEST PAGE 3 "/VERSION" simply serves to document the definition: I advise incrementing this when changes are made, so that users can tell if they have the current version. .BLANK 2.TEST PAGE 5 .CENTER ^*What are Tokens, and what are Placeholders?\* .PARAGRAPH I don't know if any formal definition exists for this. My guideline is that if it's a language element (a verb, command, instruction, etc.) it should start out as a token: if it's an option, argument or qualifier to a token, then it should start as a placeholder. This is probably understood more easily from examples. In Example#1, the RUNOFF commands such as ".DISPLAY APPENDIX", ".DAX", ".DISPLAY CHAPTER", ".DCH", ".DISPLAY ELEMENTS", etc., should be entered as tokens. The arguments to these tokens, "appendix-number-format-code", "chapter-number-format-code", "list-number-format-code", should be entered as placeholders. For example: .BLANK.NO JUSTIFY.NO FILL.RIGHT MARGIN +12.TEST PAGE 9 DEFINE TOKEN ".DISPLAY APPENDIX" - /LANGUAGE=RUNOFF - /DESCRIPTION="Changes the numbering format for appendixes (default LU)" - /TOPIC=".DISPLAY APPENDIX" .BLANK ".DISPLAY APPENDIX {number_format_code}" .BLANK END DEFINE .BLANK.TEST PAGE 9 DEFINE TOKEN ".DAX" - /LANGUAGE=RUNOFF - /DESCRIPTION="Changes the numbering format for appendixes (default LU)" - /TOPIC=".DISPLAY APPENDIX" .BLANK ".DISPLAY APPENDIX {number_format_code}" .BLANK END DEFINE .BLANK.TEST PAGE 23 DEFINE PLACEHOLDER "number_format_code" - /LANGUAGE=RUNOFF - /NOAUTO_SUBSTITUTE - /DESCRIPTION="Specifies the type of numbering to be used." - /DUPLICATION=CONTEXT_DEPENDENT - /SEPARATOR="" - /TOPIC="" - /TYPE=MENU - /LEADING="" - /TRAILING="" .BLANK "D" /DESCRIPTION="Decimal Numbers" "O" /DESCRIPTION="Octal Numbers" "H" /DESCRIPTION="Hexadecimal Numbers" "RU" /DESCRIPTION="Roman Uppercase Numerals" "RL" /DESCRIPTION="Roman Lowercase Numerals" "RM" /DESCRIPTION="Roman Mixed Case Numerals (1st letter uppercase)" "LU" /DESCRIPTION="Letters, Uppercase" "LL" /DESCRIPTION="Letters, Lowercase" "LM" /DESCRIPTION="Letters, Mixed Case (1st letter uppercase)" .BLANK END DEFINE .BLANK.JUSTIFY.FILL.RIGHT MARGIN -12 Notice the entries under "/DESCRIPTION", which is also taken from the guide. One of the big advantages of using LSE is the ability to get information and assistance on-line about the language: and the "/DESCRIPTION" field is particularly important as it is this text which appears in selection menus when expanding a choice. A little extra time here entering a good description makes the template a LOT better. .PARAGRAPH Similarly for Example#2, "ADDB2", "ADDB3", "ADDW3", etc., are entered as tokens, and "add.rx", "sum.mx", "add1.rx", etc., are entered as placeholders. There may be some adjustment to these definitions later, but this is a good place to start. I have found that the first stage of definition can be taken straight out of the documentation this way, without the need for a BNF notation. .BLANK 2.TEST PAGE 5 .CENTER ^*Document your work.\* .PARAGRAPH It's a very good idea to put some sort of header at the beginning of your definition to keep track of what it is and what you are doing to it. There is no fixed format for this. Part of my header looks like this: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 4 ! Language Sensitive Editor Language Definition for RUNOFF ! ! B. Z. Lederman ! Project Engineer Advanced Systems Development ! WU World Communications ! 67 Broad St. 28th Floor ! New York, NY 10004-2464 ! ! 26-Jun-1987 V1.1 ! 09-Jul-1987 V1.2 Text in placeholders. ! 05-Oct-1987 V1.3 Use new CHECK LANGUAGE feature. ! 22-Mar-1988 V1.4 Use menu placeholders to reduce conflicts. ! Also spell check descriptions. ! Also add "first_column"to .LEFT MARGIN. ! ! This is a user-written definition to define RUNOFF as a language ! within LSE. The definitions were originally entered in ! alphabetical order, following the "VAX DSR Quick Reference Guide". .BLANK.JUSTIFY.FILL and it then goes on with more description and a change history. .BLANK.TEST PAGE 5 .CENTER ^*Note:\* .BLANK Keep a copy of this documentation in a separate file. The reason for this is that when you enter a definition into LSE the comments are lost. Therefore, if you extract the definition again (which will be done in the next step shown below) you don't get your documentation header back. By keeping a copy in a separate file you can easily insert it again when needed. .BLANK 2.TEST PAGE 5 .CENTER ^*Normalizing the preliminary definitions.\* .PARAGRAPH After entering a lot of text, a method is needed to "normalize" it: that is, get all the definitions in alphabetical order, check to see they are all complete and syntactically correct (as far as the LSE definition is concerned), etc. The easiest way is to use LSE itself. I enter all of the definitions into LSE, then extract them all out again. This does a syntax check, and extracts them in alphabetical order. Assuming my definition file is named MACRO32B.LSE and I am defining language MACRO, the commands look like this: .BLANK.TEST PAGE 5 $ LSE/INIT=MACRO32B.LSE TEMP.MAR .BLANK 4632 lines read from file MACRO32B.LSE .BLANK [The editor will fill the screen with the normal editor window, and put any language initialization sequence on the screen. Delete this and type in Control-Z to get to the editor prompt.] .NO FLAGS BOLD .BLANK.TEST PAGE 4 LSE> extract language macro .BREAK LSE> extract token * .BREAK LSE> extract placeholder * .BREAK LSE> exit .BLANK 13311 lines written to file TEMP.MAR .BLANK $ RENAME TEMP.MAR MACRO32C.LSE .FLAGS BOLD .BLANK I believe it's a good idea to save the work done in stages, so if I make a mistake I don't loose everything I've done. Hence I've named my output file MACRO32C.LSE, and will now work on that and leave MACRO32B.LSE alone. .PARAGRAPH The name of the temporary file is not significant, but the extension is: it should be an extension which was included in the list in the "DEFINE LANGUAGE" statement so LSE will be working with the correct language. If you have no extension defined, you will have to manually enter a "SET LANGUAGE" command before any of the "EXTRACT" commands. .BLANK 2.TEST PAGE 5 .CENTER ^*First error check.\* .PARAGRAPH If you have any serious errors in your definition file, LSE will tell you as the file is read in. For example, errors such as the following may appear at the bottom of the screen: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 5 216 lines read from file USER$DEVICE:[LEDERMAN.LSE]TEMP.LSE;1 line 42 of buffer $INITIALIZE PLACEHOLDER is the name of a defined token or alias line 48 of buffer $INITIALIZE TOKEN is the name of a defined token or alias line 69 of buffer $INITIALIZE Too many parameters - reenter command with fewer parameters .NO FLAGS LOWERCASE \FILE_NAME\ .FLAGS LOWERCASE line 92 of buffer $INITIALIZE .BLANK.JUSTIFY.FILL Using an editor, you can go back to the indicated line in your definition file to look for the error. The most common one I found was leaving out an "END DEFINE command, or leaving out a hyphen ("-") as a continuation character, or having a hyphen on the last line where one should not be, or having unmatched quotation marks on text. Keep in mind that with this kind of error, the line where the error was flagged may be the beginning of the NEXT definition, and that the line with the error may be back in the previous definition. The use of an LSE template when entering the definitions greatly assists in avoiding these types of errors. .PARAGRAPH Unfortunately, if you have more than one error the messages scroll past so fast you won't be able to see them all: you may also be frustrated to find that when it's all over buffer $INITIALIZE doesn't exist. Fortunately, all of the error messages do go into buffer $MESSAGES: you can use the editor command "GOTO BUFFER $MESSAGES" to see them all, and you may want to write this buffer out to a file to save the error messages before exiting or quitting from the editor. You should fix any errors you see here before proceeding: the only error you can skip is a reference to an undefined token or placeholder. If you haven't entered all of the definitions yet, you may reference a token or placeholder you haven't defined yet, so you can ignore this until you have all of your definitions in place. Eventually, you should have a definition which does not have any errors when you read it in. .BLANK 2.TEST PAGE 5 .CENTER ^*Restore documentation and definitions.\* .PARAGRAPH If you look at this file you will find the header (comments) are now gone: as was mentioned previously, I keep a copy of my header in a separate file so I can easily restore them to my new working file. .PARAGRAPH You may also be wondering why more lines were written to the output file than were read from the input file. This is because two lines have been added to every definition. They now all look like this: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 11 DELETE TOKEN ".ADDRESS" - /LANGUAGE=MACRO DEFINE TOKEN ".ADDRESS" - /LANGUAGE=MACRO - /DESCRIPTION="Address Storage" - /TOPIC="Directives .ADDRESS" .BLANK ".ADDRESS {address}..." .BLANK END DEFINE .BLANK.JUSTIFY.FILL This is because LSE expects the extracted definition will be used to re-define an existing language, and there is no switch or qualifier to suppress this. I use the EDT editor to go through the extracted file and remove all of the "DELETE TOKEN" and "DELETE PLACEHOLDER" commands so I won't get a lot of error messages the next time I use these definitions as an initialization file. .BLANK 2.TEST PAGE 5 .CENTER ^*Checking for inconsistencies and missing definitions.\* .PARAGRAPH LSE has the ability to check a language definition. To do this, read in the definition as shown above, and at the editor prompt enter the "CHECK LANGUAGE" command with the name of the language being defined. The qualifier "/DEFINITIONS" is optional: the default is to check the definitions. The editor will tell you if there are any errors, and will also place a list of them in buffer $CHECK_LANGUAGE. It's a good idea to write out this buffer to a file. An error list may look like this: .BLANK.NO JUSTIFY.NO FILL Results for CHECK LANGUAGE MACRO32 .BLANK The following placeholders or tokens are undefined: Undefined placeholder "symbol" occurred in body of template ".ENTRY" Undefined placeholder "register_save_mask" occurred in body of template ".ENTRY" Undefined placeholder "expression" occurred in body of template ".ERROR" Undefined placeholder "shift" occurred in body of menu type placeholder "ARITHMETIC_OPERATOR" Undefined token ".ADDRESS" occurred in body of menu type placeholder "ASSEMBLER_DIRECTIVES" Undefined placeholder "tbs" occurred in body of nonterminal type placeholder "MODULE_LEVEL" .BLANK The following placeholders are unreferenced: ADDRESS_LIST ALIGNMENT_TYPE .BLANK Summary of definitions for MACRO32 484 undefined placeholders or tokens 18 unreferenced placeholders 0 conflicting package elements .BLANK 502 errors detected for MACRO32 .BLANK.JUSTIFY.FILL I've obviously edited out most of the list. What is important is that LSE will identify tokens and placeholders which are referenced but not defined (and where they were referenced), and also those which are defined but never used. This can happen because you haven't finished entering all of your definitions, or because something was misspelled, or a hyphen was used in one place and an underscore in another, etc. .BLANK 2.TEST PAGE 5 .CENTER ^*Using the SORT utility.\* .PARAGRAPH The list of errors from CHECK LANGUAGE could be very large, especially if a placeholder which is used in many tokens is not defined. A good way to reduce this list to a manageable size is with the SORT utility, and especially with the use of the /NODUPLICATE switch. For example, a section of the previous list of errors looks like this after sorting: .BLANK.NO JUSTIFY.NO FILL occurred in body of template "XORB2" occurred in body of template "XORB3" occurred in body of template "XORL2" occurred in body of template "XORL3" occurred in body of template "XORW2" occurred in body of template "XORW3" Undefined placeholder "add.rl" Undefined placeholder "add.rw" Undefined placeholder "add1len.rw" Undefined placeholder "add2.rx" Undefined placeholder "add2addr.ab" Undefined token ".ADDRESS" Undefined token ".ALIGN" Undefined token ".ASCIC" Undefined token ".ASCID" .BLANK.JUSTIFY.FILL This gives a nicely ordered list of all undefined placeholders and token, with duplicates eliminated. This list not only tells you what you have still to define, it is also helpful in spotting mis-typed tokens or placeholders. .BLANK 2.TEST PAGE 5 .CENTER ^*The need for consistency.\* .PARAGRAPH Another important use of the SORT utility is to help make the definitions consistent. This is important if you are to make your template complete and self-consistent so it will function properly. It is also important for the people who will be using it. You usually don't want to define similar language elements several different ways, because people will find the template confusing and hard to use. I find the sorted check list easier to scan for inconsistencies than the list in order of errors encountered. .BLANK 2.TEST PAGE 5 .CENTER ^*More uses for the SORT utility.\* .PARAGRAPH It is also a good idea to sort the language template itself into a temporary check file. Some portions of the RUNOFF template sorted with the /NODUPLICATE qualifier are shown below: they will all be in one file, but I will comment on them separately. .BLANK.NO JUSTIFY.NO FILL ".APPENDIX [appendix_title]" ".AUTOJUSTIFY" ".AUTOPARAGRAPH" ".AUTOSUBTITLE [header_level_number]" ".AUTOTABLE" ".BEGIN BAR" ".BLANK [nb_lines]" ".BREAK" ".CENTER [c_column]; {center_text}" ... "A list of tab stops, as in 8,16,24,32,40,..." "A single quoted character to appear left of the number." "A single quoted character to appear to the right of the number." "A string of up to 150 characters to be repeated." "An optional name to identify this document, or other comments." "An optional title for this appendix" "An optional title for this chapter" .BLANK.JUSTIFY.FILL Because they usually have one or more leading spaces, the text which expands out of a token or placeholder, or the text which displays for a placeholder which does not expand, will generally come out first in the sorted file. These can be examined for uniformity in the way the tokens are defined (though if the definitions were taken out of the manuals they should be consistent). It is also a good idea to check the informational text from the placeholders here to see if they are uniform, and read easily. .BLANK.NO JUSTIFY.NO FILL /DESCRIPTION="IF or IFNOT (Variant processing)" - /DESCRIPTION="Implicit test page value executed at start of each .. /DESCRIPTION="Indents text from both margins and separates with .. /DESCRIPTION="Indents the text n_columns (default is paragraph .. /DESCRIPTION="Indexes next word (>)" - /DESCRIPTION="Inserts change bars between .BEGIN BAR and .END BAR" .BLANK.JUSTIFY.FILL These are the description fields attached to the placeholders and tokens. When a user types in a few letters which may begin several tokens or placeholders and attempts to expand it, LSE will present a menu of the possible matches. It is these descriptions which are in the menu, and which identify what each of the language elements is supposed to do. It is therefore worthwhile spending some time to make these descriptions actually be descriptive. Also, as an example, a little more consistency in the use of the word "the" in the example above would probably be desirable. .BLANK.NO JUSTIFY.NO FILL /TOPIC=".APPENDIX" /TOPIC=".AUTOJUSTIFY" /TOPIC=".AUTOPARAGRAPH" /TOPIC=".AUTOSUBTITLE" /TOPIC=".AUTOTABLE" /TOPIC=".BEGIN BAR" .BLANK.JUSTIFY.FILL These are the HELP topics which will be used to retrieve information from a file when a user does a "HELP LANGUAGE" on a token or placeholder. This list will be very helpful in insuring that there actually is an entry in the help library for that token or placeholder, and that they are formatted and spelled the same way in both the help library and the language template. .BLANK.NO JUSTIFY.NO FILL DEFINE PLACEHOLDER "bottom_of_page_spacing" - DEFINE PLACEHOLDER "c_column" - DEFINE PLACEHOLDER "center_text" - DEFINE PLACEHOLDER "chapter_title" - DEFINE PLACEHOLDER "columns_from_right_margin" - DEFINE PLACEHOLDER "comment_text" - DEFINE PLACEHOLDER "document_name" - .BLANK DEFINE TOKEN ".AUTOJUSTIFY" - DEFINE TOKEN ".AUTOPARAGRAPH" - DEFINE TOKEN ".AUTOSUBTITLE" - DEFINE TOKEN ".AUTOTABLE" - DEFINE TOKEN ".AX" - DEFINE TOKEN ".BB" - DEFINE TOKEN ".BEGIN BAR" - DEFINE TOKEN ".BLANK" - DEFINE TOKEN ".BR" - DEFINE TOKEN ".BREAK" - DEFINE TOKEN ".CC" - .BLANK.JUSTIFY.FILL These are the actual token and placeholder definitions. It is helpful to see them together this way to see that things are all being done the same way: for example, that underscores are being used in all of the placeholders rather than hyphens (or vice versa) .BLANK 2.TEST PAGE 5 .CENTER ^*Start using the template.\* .PARAGRAPH You can often use the definition before it's finished: if there are undefined placeholders and tokens you won't be able to expand them, but you may be able to use your definitions a little within the LSE editor to test them out. You may want to do this as a check that your work is progressing in the right direction. The ultimate test of any language template is, after all, how well it works; and the best way to find out is to use it. .BLANK 2.TEST PAGE 5 .CENTER ^*When to use a menu placeholder.\* .PARAGRAPH Another very important use for the sorted language definition is to look for language definition conflicts which can be resolved with a menu placeholder. For example, I had entered all of the abbreviated RUNOFF commands as tokens. When I sorted the template, part of what I saw was this: .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 4 DEFINE TOKEN ".EB" - DEFINE TOKEN ".EBB" - DEFINE TOKEN ".EBO" - .BLANK.JUSTIFY.FILL The problem with this is that I wanted the template to be a tool for people who were not familiar with RUNOFF to be able to start up quickly, and also to make it easier for even experienced people to use RUNOFF. With the above definitions, if a user enters ".EBB" and expands it, they get the token ".ENABLE#BAR": similarly if they enter ".EBO" they get ".ENABLE#BOLDING". But if they enter ".EB" and expand it, it immediately matches and expands ".END#BAR". In some applications this may be acceptable, but what I want to happen is for the user to get a menu showing all of the possible choices. In order to do this, token ".EB" is changed to point to a menu placeholder, which in turn points to all of the choices. .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 4 DEFINE TOKEN ".EB" - /LANGUAGE=RUNOFF - /PLACEHOLDER=".EB" .BLANK.TEST PAGE 15 DEFINE PLACEHOLDER ".EB" - /LANGUAGE=RUNOFF - /NOAUTO_SUBSTITUTE - /DESCRIPTION="Enable Bolding, Enable Bar or End Bar" - /DUPLICATION=CONTEXT_DEPENDENT - /SEPARATOR="" - /TOPIC="" - /TYPE=MENU - /LEADING="" - /TRAILING="" .BLANK ".END BAR" /TOKEN/DESCRIPTION="Ends change bars" ".ENABLE BAR" /TOKEN/DESCRIPTION="Enable change bar marking" ".ENABLE BOLDING" /TOKEN/DESCRIPTION="Enable Bolding" .BLANK END DEFINE .BLANK.JUSTIFY.FILL Now if ".EB" is expanded the user will be presented with a menu giving all of the choices. .BLANK 2.TEST PAGE 5 .CENTER ^*Don't go around in circles.\* .PARAGRAPH A similar conflict exists between ".IF" and ".IFNOT": a user expanding ".IF" would never see the alternative ".IFNOT". I solved this in a similar way, but would like to point out one potential problem with menu placeholders. .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 4 DEFINE TOKEN ".IF" - /LANGUAGE=RUNOFF - /PLACEHOLDER=".IF" .BLANK.TEST PAGE 14 DEFINE PLACEHOLDER ".IF" - /LANGUAGE=RUNOFF - /NOAUTO_SUBSTITUTE - /DESCRIPTION="IF or IFNOT (Variant processing)" - /DUPLICATION=CONTEXT_DEPENDENT - /SEPARATOR="" - /TOPIC="" - /TYPE=MENU - /LEADING="" - /TRAILING="" .BLANK ".IF {variant_name}" /DESCRIPTION="Starts optional processing .. ".IFNOT" /TOKEN/DESCRIPTION="Like .IF but opposite sense of .. .BLANK END DEFINE .BLANK.JUSTIFY.FILL Notice that within the placeholder ".IF" does ^&^*NOT\*\& have the /TOKEN qualifier: it expands immediately in place from the placeholder. The reason is that if the /TOKEN qualifier was used and someone selected this entry off of the menu, it would match the ".IF" token given above. But this token points back to the ".IF" placeholder! The user can expend a lot of time and effort (and frustration) trying to get out of this loop. .PARAGRAPH In this case, ".IF" was simple enough to be able to expand it in place. If it wasn't, then the ".IF" token would have to be replaced with a real definition, and some more elaborate sequence of steps would be needed. For example, you might have to define a token with an arbitrary name, such as "~IF" or "~variant~", and have the menu entry point to that token. .PARAGRAPH You may also use menu placeholders for other types of choices. The "number_format_code" placeholder shown near the beginning is a case where the user needs to be presented with a choice of options, and a menu placeholder is the obvious solution. .BLANK 2.TEST PAGE 5 .CENTER ^*A "biased" template: imposing standards.\* .PARAGRAPH Something which may not be immediately obvious in the RUNOFF template is the fact that abbreviated commands expand out to the full command. For example, if the user expands ".FT", the editor will insert the full command ".FIRST#TITLE". This is a judgment I made when first starting to define the RUNOFF language template. I believe the full commands are much easier to read and understand than the abbreviations. For example, ".STYLE#HEADERS makes more sense to me than ".STHL"; and while ".PARAGRAPH" and ".PAGE" are obvious, ".P" might mean either one if you are not familiar with the abbreviations. The only argument against abbreviations is that they take a little longer to type in: but with LSE doing the work of expanding the text, that no longer matters. I therefore decided that I would make the abbreviated commands expand to the full commands. Other types of coding standards can be implemented using LSE templates, which is another of their values. Of course, a determined person can circumvent them (or just not use the LSE at all), but most people will take the path of least resistance and use the templates as they are provided, if they work properly and easily. .BLANK 2.TEST PAGE 5 .CENTER ^*Use a spelling checker (and get some side benefits).\* .PARAGRAPH If you have a spelling checker, by all means use it on the language template. Even the best of us hit the wrong key occasionally. I set up a separate personal dictionary for use with DECSpell for each language template, so odd "words" will go into this special dictionary. .PARAGRAPH There can be an interesting benefit to using a spelling checker. When I defined the MACRO32 template, I ended up with the assembler instructions and mnemonics as valid words in the dictionary (I checked them fairly carefully against the manual before adding them). I then made a copy of the dictionary, edited out the LSE terms, and now have a dictionary that allows me to spell check my Macro programs. The spelling checker will ignore all valid instructions and operators, and I can more easily check the spelling of my comments and documentation. This also lets me use the spelling checker to spot where I may have mis-typed a variable name. .BLANK 2.TEST PAGE 5 .CENTER ^*Setting up a help file.\* .PARAGRAPH It's a good idea to have some sort of help file, so the user will receive assistance with the "HELP LANGUAGE" key. This is going to largely be a matter of entering text which defines language elements. There are three factors which must match between the language template and the help file. .BLANK The name of the help library must match that given in the /HELP_LIBRARY qualifier of the DEFINE LANGUAGE definition. .BLANK The first entry or set of entries must match that given in the /TOPIC_STRING qualifier of the DEFINE LANGUAGE definition. .BLANK The individual entries must match the entries in the /TOPIC qualifiers in the token and placeholder definitions. .PARAGRAPH What follows is a sort section of my help file for the RUNOFF definition. These entries may be matched with the examples given earlier in the paper. It is also helpful to look at the templates supplied with LSE to see how they use multiple keywords in topic entries. .BLANK.NO JUSTIFY.NO FILL.TEST PAGE 11 1 RNO .BLANK This is a user written file containing information on RUNOFF "language" commands. The idea is to use it with the Language Sensitive Editor, though it should work on it's own. It doesn't have entries for the abbreviated commands, because the LSE definitions point the abbreviated command to the full command entry in this help file. .BLANK B. Z. Lederman 25-Jun-1987 V1.0 .BLANK.TEST PAGE 5 2 .APPENDIX .APPENDIX [appendix_title] .BLANK Starts a new appendix on a new page. .BLANK.TEST PAGE 6 2 .AUTOJUSTIFY .AUTOJUSTIFY .BLANK Turns on justification and filling at the start of each header level, chapter, appendix, note, and footnote. On by default. .BLANK.TEST PAGE 7 2 .AUTOPARAGRAPH .AUTOPARAGRAPH .BLANK Starts a new paragraph each time a blank line or a line that begins with a space or tab is encountered in the input file. (See .AUTOTABLE and .SET PARAGRAPH). Default is .NO AUTOPARAGRAPH .JUSTIFY.FILL .PARAGRAPH In addition to the "CHECK LANGUAGE" command with the default qualifier "/DEFINITIONS" to check the language definitions, there is also a "/HELP" qualifier to check the help definitions. I have not found this feature to be of much use. All it appears to do is to compare the name of the token or placeholder with the text in the /TOPIC string. In my RUNOFF template, all of the abbreviated RUNOFF commands are pointed to the appropriate full command in the help file, so CHECK LANGUAGE flagged half of my definitions as being in error when I don't consider them to be erroneous. What would help a lot more is if LSE would check to see if a /TOPIC actually existed in the help file, and perhaps some SPRs might be in order to request this function.