390 lines
12 KiB
C
390 lines
12 KiB
C
|
/*** GRAMMAR.H -- Contains grammar of NMAKE ************************************
|
|||
|
*
|
|||
|
* Copyright (c) 1988-1989, Microsoft Corporation. All rights reserved.
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Module contains grammar of NMAKE and definitions used by lexer & parser
|
|||
|
*
|
|||
|
* Revision History:
|
|||
|
* 08-Oct-1989 SB Added QUOTE_ and NOQ and QUO to handle OS/2 1.2 quoted names
|
|||
|
* 31-Jul-1989 SB Added BKS, DEF and BEG to add lookahead to the lexer
|
|||
|
* 18-May-1989 SB Added BKSLH_ definition for use by lexer's nameStates[]
|
|||
|
*
|
|||
|
*******************************************************************************/
|
|||
|
|
|||
|
/*------------------------------------------------------------------------------
|
|||
|
*
|
|||
|
*
|
|||
|
* This file contains the grammar for nmake.
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
* e is the symbol epsilon
|
|||
|
*
|
|||
|
*
|
|||
|
* nonterminals begin w/ capitals
|
|||
|
*
|
|||
|
*
|
|||
|
* terminals begin w/ lower-case letters
|
|||
|
*
|
|||
|
*
|
|||
|
* terminals: name newline newlineWhitespace semicolon colon equals string e
|
|||
|
* doublecolon value
|
|||
|
*
|
|||
|
*
|
|||
|
* Makefile -> e |
|
|||
|
* BlankLines Makefile |
|
|||
|
* newline name Body Makefile
|
|||
|
*
|
|||
|
* Body -> NameList Separator BuildInfo |
|
|||
|
* equals value
|
|||
|
*
|
|||
|
* NameList -> e |
|
|||
|
* name NameList
|
|||
|
*
|
|||
|
* Commands -> e |
|
|||
|
* MoreBuildLines |
|
|||
|
* semicolon string MoreBuildLines
|
|||
|
*
|
|||
|
* MoreBuildLines -> e |
|
|||
|
* newlineWhitespace string MoreBuildLines |
|
|||
|
* newline MoreBuildLines
|
|||
|
*
|
|||
|
* BlankLines -> e |
|
|||
|
* newline BlankLines |
|
|||
|
* newlineWhitespace BlankLines
|
|||
|
*
|
|||
|
* BuildInfo -> e |
|
|||
|
* NameList Commands
|
|||
|
*
|
|||
|
* Separator -> colon | doublecolon
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
* note: a "string" is everything from the current input character up
|
|||
|
* to the first newline which is not preceded by a backslash, or
|
|||
|
* end of file (whichever comes first). a macro "value" is the
|
|||
|
* same as a "string" with the exception that comments are stripped
|
|||
|
* from it (a comment ending in a backslash does not cause the
|
|||
|
* value to be continued on the next line).
|
|||
|
*
|
|||
|
*/
|
|||
|
/*------------------------------------------------------------------------------
|
|||
|
*
|
|||
|
* Compute FIRST() and FOLLOW() for each nonterminal in order to construct
|
|||
|
* parse table (it'd be nice to have a simple utility to build the
|
|||
|
* table, but it's still a pretty easy thing to do by hand).
|
|||
|
*
|
|||
|
*
|
|||
|
* FIRST(Makefile) = e newline FIRST(BlankLines)
|
|||
|
* = e newline newlineWhitespace
|
|||
|
*
|
|||
|
* FIRST(Body) = equals FIRST(NameList) FIRST(Separator)
|
|||
|
* = equals name colon doublecolon
|
|||
|
*
|
|||
|
* FIRST(NameList) = e name
|
|||
|
*
|
|||
|
* FIRST(Commands) = e semicolon FIRST(BuildLine)
|
|||
|
* = e semicolon newlineWhitespace
|
|||
|
*
|
|||
|
* FIRST(MoreBuildLines) = e FIRST(BuildLine) FIRST(BlankLines)
|
|||
|
* = e newlineWhitespace newline
|
|||
|
*
|
|||
|
* FIRST(BlankLines) = e newline newlineWhitespace
|
|||
|
*
|
|||
|
* FIRST(BuildInfo) = FIRST(NameList) FIRST(Commands)
|
|||
|
* = e name semicolon newlineWhitespace
|
|||
|
*
|
|||
|
* FIRST(Separator) = colon doublecolon
|
|||
|
*
|
|||
|
*
|
|||
|
* ---------------------------------------------------------------
|
|||
|
*
|
|||
|
*
|
|||
|
* FOLLOW(Makefile) = $
|
|||
|
*
|
|||
|
* FOLLOW(Body) = FIRST(Makefile) FOLLOW(Makefile)
|
|||
|
* = newline newlineWhitespace $
|
|||
|
*
|
|||
|
* FOLLOW(NameList) = FIRST(Commands) FIRST(MoreBuildLines)
|
|||
|
* colon FOLLOW(Body)
|
|||
|
* = colon semicolon newlineWhitespace
|
|||
|
* newline $
|
|||
|
*
|
|||
|
* FOLLOW(Commands) = FOLLOW(Body)
|
|||
|
* = newline newlineWhitespace $
|
|||
|
*
|
|||
|
* FOLLOW(MoreBuildLines) = FOLLOW(Commands)
|
|||
|
* = newline newlineWhitespace $
|
|||
|
*
|
|||
|
* FOLLOW(BlankLines) = FIRST(Body) FOLLOW(Makefile)
|
|||
|
* = newlineWhitespace newline $
|
|||
|
*
|
|||
|
* FOLLOW(BuildInfo) = FOLLOW(Body)
|
|||
|
* = newline newlineWhitespace $
|
|||
|
*
|
|||
|
* FOLLOW(Separator) = FIRST(BuildInfo) FOLLOW(Body)
|
|||
|
* = name semicolon newlineWhitespace
|
|||
|
* newline $
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
/*------------------------------------------------------------------------------
|
|||
|
*
|
|||
|
* for building the table, I number the productions:
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
* 0. Makefile -> e
|
|||
|
*
|
|||
|
* 1. Makefile -> BlankLines Makefile
|
|||
|
*
|
|||
|
* 2. MakeFile -> newline name Body Makefile
|
|||
|
*
|
|||
|
* 3. Body -> NameList Separator BuildInfo
|
|||
|
*
|
|||
|
* 4. Body -> equals value
|
|||
|
*
|
|||
|
* 5. NameList -> e
|
|||
|
*
|
|||
|
* 6. NameList -> name NameList
|
|||
|
*
|
|||
|
* 7. Commands -> e
|
|||
|
*
|
|||
|
* 8. Commands -> MoreBuildLines
|
|||
|
*
|
|||
|
* 9. Commands -> semicolon string MoreBuildLines
|
|||
|
*
|
|||
|
* 10. MoreBuildLines -> newlineWhiteSpace string MoreBuildLines
|
|||
|
*
|
|||
|
* 11. MoreBuildLines -> e
|
|||
|
*
|
|||
|
* 12. MoreBuildLines -> newline MoreBuildLines
|
|||
|
*
|
|||
|
* 13. BlankLines -> e
|
|||
|
*
|
|||
|
* 14. BlankLines -> newline BlankLines
|
|||
|
*
|
|||
|
* 15. BlankLines -> newlineWhitespace BlankLines
|
|||
|
*
|
|||
|
* 16. BuildInfo -> e
|
|||
|
*
|
|||
|
* 17. BuildInfo -> NameList Commands
|
|||
|
*
|
|||
|
* 18. Separator -> colon
|
|||
|
*
|
|||
|
* 19. Separator -> doublecolon
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
/*------------------------------------------------------------------------------
|
|||
|
*
|
|||
|
* NOTE THAT THIS GRAMMAR IS NOT LL(1) (it's really LL(2) because we need
|
|||
|
* an extra symbol of lookahead to decide which production to use in
|
|||
|
* a few cases)
|
|||
|
*
|
|||
|
*
|
|||
|
* the resulting parse table (empty entries are error conditions):
|
|||
|
*
|
|||
|
*
|
|||
|
* newline-
|
|||
|
* White- semi- double-
|
|||
|
* |name |newline| space | colon | colon | colon |equals |$ |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* A | | | | | | | | |
|
|||
|
* Makefile | | 1,2 | 1 | | | | | 0 |
|
|||
|
* | | | | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* B | | | | | | | | |
|
|||
|
* Blank- | | 13,14 | 13[15]| | | | | 13 |
|
|||
|
* Lines | | | -- | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* C | | | | | | | | |
|
|||
|
* More- | | 11,12 | 10 | | | | | 11 |
|
|||
|
* Build- | | | | | | | | |
|
|||
|
* Lines -----------------------------------------------------------------
|
|||
|
* D | | | | | | | | |
|
|||
|
* Commands | | 7 | [7]8 | 9 | | | | 7 |
|
|||
|
* | | | - | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* E | | | | | | | | |
|
|||
|
* Body | 3 | | | | 3 | | 4 | |
|
|||
|
* | | | | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* F | | | | | | | | |
|
|||
|
* NameList | 6 | 5 | 5 | 5 | 5 | 5 | | 5 |
|
|||
|
* | | | | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* G | | | | | | | | |
|
|||
|
* Build- | 17 | 16 |[16]17 | 17 | | | | 16 |
|
|||
|
* Info | | | -- | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
* H | | | | | | | | |
|
|||
|
* Separ- | | | | | 18 | 19 | | |
|
|||
|
* ator | | | | | | | | |
|
|||
|
* -----------------------------------------------------------------
|
|||
|
*
|
|||
|
* G2 -- always uses 17 -- anytime the user puts a line beginning w/
|
|||
|
* whitespace immediately after a target-dependency line, it's
|
|||
|
* a build line. Same for D2.
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* IMPORTANT: IF YOU CHANGE THE VALUES OF ANY OF THE FOLLOWING
|
|||
|
* CONSTANTS FOR TERMINAL OR NONTERMINAL SYMBOLS, YOU MUST ADJUST
|
|||
|
* THE APPROPRIATE TABLES (AND STRING LITERALS) ACCORDINGLY.
|
|||
|
*
|
|||
|
* Nonterminal symbols first (these are used to index the parse table
|
|||
|
* along the first dimension):
|
|||
|
*
|
|||
|
* define nonterminals . . .
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
#define MAKEFILE 0x00 /* productions w/ 2 */
|
|||
|
#define BLANKLINES 0x01 /* alternatives in a */
|
|||
|
#define MOREBUILDLINES 0x02 /* table entry must */
|
|||
|
#define COMMANDS 0x03 /* come first (so */
|
|||
|
#define BODY 0x04 /* that I can use */
|
|||
|
#define NAMELIST 0x05 /* them as array */
|
|||
|
#define BUILDINFO 0x06 /* subscripts when */
|
|||
|
#define SEPARATOR 0x07 /* resolving the */
|
|||
|
/* conflict) */
|
|||
|
|
|||
|
#define START MAKEFILE
|
|||
|
#define LAST_PRODUCTION SEPARATOR
|
|||
|
|
|||
|
/*
|
|||
|
* Now the terminal symbols (the 4 low bits of which are used to index
|
|||
|
* the parse table alone 2nd dimension -- bit 5 simply distinguishes
|
|||
|
* tokens from nonterminals in productions):
|
|||
|
*/
|
|||
|
|
|||
|
#define NAME 0x10 /* TOKEN_MASK | 0 */
|
|||
|
#define NEWLINE 0x11 /* TOKEN_MASK | 1 */
|
|||
|
#define NEWLINESPACE 0x12 /* TOKEN_MASK | 2 */
|
|||
|
#define SEMICOLON 0x13 /* TOKEN_MASK | 3 */
|
|||
|
#define COLON 0x14 /* TOKEN_MASK | 4 */
|
|||
|
#define DOUBLECOLON 0x15 /* etc. */
|
|||
|
#define EQUALS 0x16
|
|||
|
#define ACCEPT 0x17 /* this is $ */
|
|||
|
#define STRING 0x18 /* no columns in table*/
|
|||
|
#define VALUE 0x19 /* for these two */
|
|||
|
|
|||
|
/*
|
|||
|
* Error values -- these are equal to the error exit code minus 1000
|
|||
|
* if you change them, you must change the corresponding values in
|
|||
|
* nmmsg.txt
|
|||
|
*/
|
|||
|
|
|||
|
#define MACRO 0x20 /* ERROR_MASK | 0 */
|
|||
|
#define SYNTAX 0x21 /* ERROR_MASK | 1 */
|
|||
|
#define SEPRTR 0x22 /* ERROR_MASK | 2 */
|
|||
|
#define SEPEQU 0x23 /* ERROR_MASK | 3 */
|
|||
|
#define NAMES 0x24 /* ERROR_MASK | 4 */
|
|||
|
#define NOTARG 0x25 /* ERROR_MASK | 5 */
|
|||
|
#define LEXER 0x26 /* ERROR_MASK | 6 */
|
|||
|
#define PARSER 0x27 /* ERROR_MASK | 7 */
|
|||
|
|
|||
|
/*
|
|||
|
* Parser actions -- these are indexes into the "action" function table,
|
|||
|
* telling the parser which function to call at a certain point in
|
|||
|
* a production
|
|||
|
*/
|
|||
|
|
|||
|
#define DONAME 0x40 /* ACTION_MASK | 0 */
|
|||
|
#define DONAMELIST 0x41
|
|||
|
#define DOMACRO 0x42
|
|||
|
#define DODEPENDS 0x43
|
|||
|
#define DOLASTNAME 0x44
|
|||
|
#define DOBUILDCMDS 0x45
|
|||
|
|
|||
|
/*
|
|||
|
* a few macros to simplify dealing w/ tokens:
|
|||
|
*/
|
|||
|
|
|||
|
#define TOKEN_MASK 0x10
|
|||
|
#define ERROR_MASK 0x20
|
|||
|
#define ACTION_MASK 0x40
|
|||
|
#define AMBIG_MASK 0x80 /* conflict in table */
|
|||
|
#define LOW_NIBBLE 0x0F
|
|||
|
|
|||
|
/*
|
|||
|
* values for alternate productions table
|
|||
|
* (a YES in the slot for a given input token and a given nonterminal
|
|||
|
* on top of the stack means use the next production (+1) from the
|
|||
|
* one given in the production table)
|
|||
|
*/
|
|||
|
|
|||
|
#define YES 1
|
|||
|
#define NO 0
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* values for lexer's state machine that recognizes names
|
|||
|
* append an underscore to distinguish these from parser's tokens
|
|||
|
*/
|
|||
|
|
|||
|
#define DEFAULT_ 0x00 /* char not defined */
|
|||
|
#define COMMENT_ 0x01 /* below */
|
|||
|
#define EQUALS_ 0x02
|
|||
|
#define SEMICOLON_ 0x03
|
|||
|
#define COLON_ 0x04
|
|||
|
#define WHITESPACE_ 0x05 /* \t and ' ' */
|
|||
|
#define NEWLINE_ 0x06 /* \n and EOF */
|
|||
|
#define DOLLAR_ 0x07
|
|||
|
#define OPENPAREN_ 0x08
|
|||
|
#define CLOSEPAREN_ 0x09
|
|||
|
#define MACROCHAR_ 0x0A /* A-Z,a-z,0-9,_ */
|
|||
|
#define OPENCURLY_ 0x0B
|
|||
|
#define CLOSECURLY_ 0x0C
|
|||
|
#define BKSLSH_ 0x0D
|
|||
|
#define QUOTE_ 0x0E
|
|||
|
|
|||
|
#define STAR_ 0x0B /* only for strings: */
|
|||
|
#define SPECIAL1_ 0x0C /* @ * < ? */
|
|||
|
#define SPECIAL2_ 0x0D /* B F D R */
|
|||
|
#define BACKSLASH_ 0x03 /* don't need semi if */
|
|||
|
/* we have backslash */
|
|||
|
/* (names need ; but */
|
|||
|
/* strings need \) */
|
|||
|
/*
|
|||
|
* values for state tables -- for error values, mask off the error bit (0x20)
|
|||
|
* to get the message number.
|
|||
|
*/
|
|||
|
|
|||
|
#define OK 0x40 /* means accept token */
|
|||
|
#define BEG 0x00 /* means beginning */
|
|||
|
#define DEF 0x01 /* means normal name */
|
|||
|
#define BKS 0x0f /* processing bkslash */
|
|||
|
#define PAR 0x20 /* close paren missing*/
|
|||
|
#define CHR 0x21 /* bad char in macro */
|
|||
|
#define BAD 0x22 /* single $ w/o macro */
|
|||
|
#define EQU 0x23 /* substitution w/o = */
|
|||
|
#define NAM 0x24 /* illegal macro name */
|
|||
|
#define SEQ 0x25 /* subst w/o strings */
|
|||
|
#define NOQ 0x26 /* no matching quote */
|
|||
|
#define QUO 0x27 /* illegal " in name */
|