xcpj file grammar

In the following, ISO/IEC 14977:1996 Information technology -- Syntactic metalanguage -- Extended BNF is used to define the EBNF syntax for expressing the xcpj file grammar. The grammar is presented in bottom up order (i.e. there is a tendency to define non-terminals before they are referenced)

Let stringLiteral stand for a double quoted string literal and intLiteral for an integer literal.

Configurations


targetType =
    '"Application"' |
    '"Static Library"' |
    '"Console Application"' |
    '"Dynamic-Link Library"' |
    '"Utility Project"';

compilerName =
    '"vc6"' | '"vc8"' | '"vc9"';

(* E.g. "Debug" *)
configName = stringLiteral;

(* E.g. "Win32" *)
platformName = stringLiteral;

(* E.g. "Debug|Win32" *)
configAndPlatform = stringLiteral;

(* E.g. "WinCE" *)
tagName = stringLiteral;

(* E.g. "Debug|Win32" ["Unicode"] *)
singleConfigDef =
    configAndPlatform,
    [
    '[', {tagName}, ']'
    ];

configsDef =
    'config',
    '{',
    { singleConfigDef },
    '}';

(* E.g. "Debug|WinCE|vc8"
   Each string between the | must be either a
   tagName, configName, platformName,
   compilerName or targetType
*)
configRef = stringLiteral;

(* E.g. ("Debug|WinCE|vc8", "Win32") *)
configRefList =
    '(',
    [configRef, { ',', configRef } ],
    ')';

C++ Compiler switches


cppBoolSwitch1 =
    '/GR' | '/GL' | '/GS' | '/Gy' | '/fp:except';

cppBoolSwitch2 =
    '/nologo' | '/Oi' | '/Op' | '/Oy' | '/GT' |
    '/X' | '/C' | '/GF' | '/Gm' | '/RTCc' |
    '/Za' | '/J' | '/openmp' | '/Fx' | '/doc' |
    '/WX' | '/Wp64' | '/showIncludes' | '/u' |
    '/FC' | '/Zl' | '/Zc:wchar_t' |
    '/Zc:forScope' | '/QRinterwork' | '/QRfpe';

cppEnumSwitch =
    '/Od' | '/O1' | '/O2' | '/Ox' |
    '/Ob1' | '/Ob2' |
    '/Ot' | '/Os' |
    '/EHsc' | '/EHa' | '/GX' |
    '/RTCs' | '/RTCu' | '/RTC1' | '/RTCsu' |
    '/GZ' |
    '/MT' | '/MTd' | '/MD' | '/MDd' |
    '/Zp1' | '/Zp2' | '/Zp4' | '/Zp8' | '/Zp16' |
    '/QRarch4' | '/QRarch5' | '/QRarch4t' |
    '/QRarch5t' |
    '/TC' | '/TP' |
    '/arch:SSE' | '/arch:SSE2' |
    '/fp:precise' | '/fp:strict' | '/fp:fast' |
    '/FA' | '/FAcs' | '/FAc' | '/FAs' |
    '/FR' | '/Fr' |
    '/W0' | '/W1' | '/W2' | '/W3' | '/W4' |
    '/Z7' | '/Zi' | '/ZI' |
    '/Gd' | '/Gr' | '/Gz' |
    '/errorReport:prompt' |
    '/errorReport:queue' |
    '/clr' | '/clr:pure' | '/clr:safe' |
    '/clr:noAssembly' | '/clr:oldSyntax';

cppStrArgSwitch =
    '/Fd' | '/Fe' | '/Fo' | '/Fp' | '/FR';

cppListStrArgSwitch =
    '/I' | '/D' | '/FI' | '/FU' | '/U';

cppPchSwitch =
    '/Yc' | '/Yu' | '/YX';

cppCompilerSwitch =
    cppBoolSwitch1, ['-'] |
    cppBoolSwitch2 |
    cppEnumSwitch |
    cppStrArgSwitch, stringLiteral |
    cppListStrArgSwitch, stringLiteral |
    cppPchSwitch [stringLiteral];

Resource Compiler switches


rcBoolSwitch =
    '/x' | '/v';

rcStrArgSwitch =
    '/fo';

rcListStrArgSwitch =
    '/I' | '/d' | '/u';

rcCompilerSwitch =
    rcBoolSwitch |
    rcStrArgSwitch, stringLiteral |
    rcListStrArgSwitch, stringLiteral;

Linker switches


linkBoolSwitch =
    '/NOLOGO' | '/NOENTRY' | '/IGNOREIDL' |
    '/NOASSEMBLY' | '/DELAY:UNLOAD' | '/RELEASE' |
    '/DEBUG' | '/SWAPRUN:CD' | '/SWAPRUN:NET' |
    '/PROFILE' | '/MAPINFO:EXPORTS' | '/MAP' |
    '/NODEFAULTLIB' | '/DELAYSIGN' |
    '/CLRUNMANAGEDCODECHECK';

machine =
    'X86' | 'IX86' | 'I386' | 'AM33' |
    'ARM' | 'EBC' | 'IA64' | 'M32R' |
    'MIPS' | 'MIPS16' | 'MIPSFPU' |
    'MIPSFPU16' | 'MIPSR41XX' | 'SH3' |
    'SH3DSP' | 'SH4' | 'SH5' | 'THUMB' |
    'X64';

subsystem =
    'CONSOLE' | 'WINDOWS' |
    'NATIVE' | 'EFI_APPLICATION' |
    'EFI_BOOT_SERVICE_DRIVER' |
    'EFI_ROM' | 'EFI_RUNTIME_DRIVER' |
    'POSIX' | 'WINDOWSCE';

opt =
    'NOREF' | 'REF' | 'NOICF' | 'ICF' |
    'NOWIN98' | 'WIN98';

linkEnumSwitch =
    '/MACHINE:', machine |
    '/SUBSYSTEM:', subsystem |
    '/OPT:', opt |
    '/DRIVER', [':UPONLY' | ':WDM'] |
    '/ASSEMBLYDEBUG', [':DISABLE'] |
    '/INCREMENTAL', [':NO'] |
    '/MANIFEST', [':NO'] |
    '/FIXED', [':NO'] |
    '/TSAWARE', [':NO'] |
    '/LARGEADDRESSAWARE', [':NO'] |
    '/LTCG', [':PGINSTRUMENT' | ':PGOPTIMIZE' | ':PGUPDATE'] |
    '/VERBOSE', [':LIB'] |
    '/ALLOWISOLATION:NO' |
    '/CLRTHREADATTRIBUTE:', ('MTA' | 'STA') |
    '/CLRIMAGETYPE:', ('IJW' | 'PURE' | 'SAFE') |
    '/ERRORREPORT:', ('NONE' | 'PROMPT' | 'QUEUE');

linkStrArgSwitch =
    '/DEF' | '/BASE' | '/ENTRY' | '/IDLOUT' |
    '/TLBOUT' | '/TLBID' | '/PGD' | '/ORDER' |
    '/MANIFESTFILE' | '/OUT' | '/VERSION' |
    '/IMPLIB' | '/PDB' | '/PDBSTRIPPED' |
    '/MIDL' | '/KEYFILE' | '/KEYCONTAINER' |
    '/MAP';

linkListStrArgSwitch =
    '/MANIFESTDEPENDENCY' |
    '/ASSEMBLYMODULE' | '/ASSEMBLYRESOURCE' |
    '/ASSEMBLYLINKRESOURCE' |
    '/INCLUDE' | '/DELAYLOAD' |
    '/NODEFAULTLIB' | '/LIBPATH';

reserve = intLiteral;
commit = intLiteral;
libraryName = stringLiteral;

linkSwitch =
    linkBoolSwitch |
    linkEnumSwitch |
    linkStrArgSwitch, ':', stringLiteral |
    linkListStrArgSwitch, ':', stringLiteral |
    ('/HEAP:' | '/STACK'), reserve, [',', commit] |
    libraryName;

Applying compiler and linker switches

This part of the grammar concerns the incremental addition or removal of compiler or linker switches, either to all configurations or else to specified configurations.


cppSpec =
    ('+' | '-'),
    'cpp',
    [ configRefList ],
    '{',
    { cppCompilerSwitch },
    '}';

rcSpec =
    ('+' | '-'),
    'rc',
    [ configRefList ],
    '{',
    { rcCompilerSwitch },
    '}';

linkSpec =
    ('+' | '-'),
    'link',
    [ configRefList ],
    '{',
    { linkSwitch },
    '}';

Project files

This is the relevant part of the grammar involved with specifying the files that comprise the project. It supports nested directories, wild cards, recursion, flattening, renaming.


pattern = stringLiteral;

directoryName = stringLiteral;
folderName = stringLiteral;

(* E.g. +["*.cpp" "*.h"] *)
nameFilter =
    ['-' | '+'],
    pattern | '[', {pattern}, ']';

(* E.g. directories -[] *)
directoriesFilterDef =
    'directories', nameFilter;

(* E.g. +cpp{/O1} *)
fileOpt =
    'exclude' |
    cppSpec |
    rcSpec;

(* E.g. "*.cpp" flat * : +cpp{/D "BLAH"} *)
filesSpec =
    nameFilter,
    [ ['flat'], '*' ],
    [ ':', fileOpt, {',', fileOpt} ];

dirElement =
    filesSpec |
    directoryName, ['as', folderName],
    directoryStructure;

directoryStructure =
    '{', {dirElement}, '}';

Entire xcpj file


varName = identifier;
varValue = stringLiteral;

path = stringLiteral;
logicalPathToProjDir = path;

subProjSpec =
    'subproj',
    '{',
    { logicalPathToProjDir },
    '}';

toolFilesSpec =
    'toolFiles',
    '{',
    { path },
    '}';

description = stringLiteral;
command = stringLiteral;

eventSpec =
    ('prebuildevent' | 'prelinkevent' |
    'postbuildevent'),
    [ configRefList ],
    '{',
    description,
    command,
    '}';

genKey =
    'OutputDirectory' |
    'IntermediateDirectory' |
    'DeleteExtensionsOnClean' |
    'BuildLogFile' |
    'InheritedPropertySheets' |
    'ConfigurationType' |
    'UseOfMFC' |
    'UseOfATL' |
    'ATLMinimizesCRunTimeLibraryUsage' |
    'CharacterSet' |
    'ManagedExtensions' |
    'WholeProgramOptimization';

genSettingsSpec =
    'general',
    [ configRefList ],
    '{',
    { genKey, '=', stringLiteral },
    '}';

xcpjElement =
    'xcpp' |
    'export' |
    '$', varName, '=', varValue |
    '@import', path |
    cppSpec |
    rcSpec
    LinkSpec
    subProjSpec |
    configsDef |
    directoriesFilterDef |
    toolFilesSpec |
    eventSpec;

xcpjFile =
    '$TARGET_TYPE', '=', targetType,
    '$ROOT_TO_PROJDIR', '=', logicalPathToProjDir,
    { xcpjElement },
    directoryStructure;