Forge
IntroductionThis is the public C API people who mainly want to use Hammer in a host application can use to parse and compile scripts, and register host-specific commands, functions and properties. For the actual C++ implementation of the parser, see the CParser class. Functions
LEOAddBuiltInFunctionsAndOffsetInstructionsvoid LEOAddBuiltInFunctionsAndOffsetInstructions( struct TBuiltInFunctionEntry *inEntries, size_t firstBuiltInFunctionInstruction ); DiscussionRegister the built-in function names and their corresponding instructions in inEntries with the Forge parser. The array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstBuiltInFunctionInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. LEOAddBuiltInVariablesvoid LEOAddBuiltInVariables( struct TBuiltInVariableEntry *inEntries ); DiscussionAdd one or more variable names to the table of Forge's built-in variables. You can reference these using "the <name>", e.g. "the result" or "the download". LEOAddGlobalPropertiesAndOffsetInstructionsvoid LEOAddGlobalPropertiesAndOffsetInstructions( struct TGlobalPropertyEntry *inEntries, size_t firstGlobalPropertyInstruction ); DiscussionRegister the global property names and their corresponding instructions in inEntries with the Forge parser. The property array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstGlobalPropertyInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. LEOAddHostCommandsAndOffsetInstructionsvoid LEOAddHostCommandsAndOffsetInstructions( struct THostCommandEntry *inEntries, size_t firstHostCommandInstruction ); DiscussionRegister the syntax and the corresponding instructions for host-specific commands in inEntries with the Forge parser. The array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstGlobalPropertyInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. LEOAddHostFunctionsAndOffsetInstructionsvoid LEOAddHostFunctionsAndOffsetInstructions( struct THostCommandEntry *inEntries, size_t firstHostCommandInstruction ); DiscussionRegister the syntax and the corresponding instructions for host-specific functions in inEntries with the Forge parser (anything that can be a term in an expression, really, it doesn't have to be a function in the traditional sense.). The array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstGlobalPropertyInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. LEOAddNumberConstantsvoid LEOAddNumberConstants( struct TNumberConstantEntry *inEntries ); DiscussionAdd one or more numeric constants to the table of Forge's built-in constants. See Also LEOAddOperatorsAndOffsetInstructionsvoid LEOAddOperatorsAndOffsetInstructions( struct TOperatorEntry *inEntries, size_t firstOperatorInstruction ); DiscussionRegister the syntax and the corresponding instructions for binary operators in inEntries with the Forge parser. The array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstOperatorInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. All instructions that implement a binary operator must pop exactly two values from the end of the stack and push a single result back. (or pop one off the stack and clean up/initialize the last one using kLEOInvalidateReferences) LEOAddStringConstantsvoid LEOAddStringConstants( struct TStringConstantEntry *inEntries ); DiscussionAdd one or more string constants to the table of Forge's built-in constants. See Also LEOAddUnaryOperatorsAndOffsetInstructionsvoid LEOAddUnaryOperatorsAndOffsetInstructions( struct TUnaryOperatorEntry *inEntries, size_t firstUnaryOperatorInstruction ); DiscussionRegister the syntax and the corresponding instructions for unary operators in inEntries with the Forge parser. The array passed in is copied into Forge's internal tables, and its end detected by an entry with identifier type ELastIdentifier_Sentinel. You must have registered all instructions referenced here using the same call to LEOAddInstructionsToInstructionArray, and you must pass in the index of the first instruction as returned by that call in firstUnaryOperatorInstruction. If you want to specify an invalid instruction (e.g. to indicate a read-only or write-only property), you must use INVALID_INSTR2, as INVALID_INSTR is 0 and would thus be undistinguishable from your first instruction. All instructions that implement a unary operator must pop exactly one value from the end of the stack and push a single result back. (or clean up/initialize it using kLEOInvalidateReferences) LEOCleanUpDisplayInfoTablevoid LEOCleanUpDisplayInfoTable( LEODisplayInfoTable *inTable ); DiscussionFree the memory occupied by this display info table. See Also LEOCleanUpParseTreevoid LEOCleanUpParseTree( LEOParseTree *inTree ); DiscussionFree the memory for a parse tree created by LEOParseTreeCreateFromUTF8Characters or LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters. See Also LEODebugPrintParseTreevoid LEODebugPrintParseTree( LEOParseTree *inTree ); DiscussionPrint a description of a particular parse tree to the console, to help in debugging the engine. LEODisplayInfoTableApplyToTextvoid LEODisplayInfoTableApplyToText( LEODisplayInfoTable *inTable, const char *code, size_t codeLen, char **outText, size_t *outLength, size_t *ioCursorPosition, size_t *ioCursorEndPosition ); Parameters
DiscussionReformat the given script text (which must be the same text that was passed to LEOParseTreeCreateFromUTF8Characters() to generate the parse tree from which this display info table was generated), adjusting its indentation to indicate the structure of the script (i.e. which commands belong to which handler, and where a handler starts or ends), and the places where the parser encountered errors. See Also LEODisplayInfoTableCreateForParseTreeLEODisplayInfoTable* LEODisplayInfoTableCreateForParseTree( LEOParseTree *inTree ); DiscussionExtract information from the parse tree that is of interest for displaying the script in an editor. This includes information on which line cause indentation to change as well as a list of handlers and what line in the script they start at for quick navigation. See Also LEODisplayInfoTableGetHandlerInfoAtIndexvoid LEODisplayInfoTableGetHandlerInfoAtIndex( LEODisplayInfoTable *inTable, size_t inIndex, const char **outName, size_t *outLine, bool *outIsHandlerEnd, bool *outIsCommand ); DiscussionReturn information about a particular handler in this script, such as its name, type, and what line in the script it starts on. Indexes start at 0. If there are no more handlers in the display info table, this sets outName to NULL. The char* pointers returned in outName are owned by the display info table. Do not try to free() them. See Also LEOLoadNativeHeadersFromFilevoid LEOLoadNativeHeadersFromFile( const char *filepath ); DiscussionLoad syntax for 'native calls' (i.e. native operating system APIs as you would call them from C, Objective C, C# or Pascal) from the specified .hhc header file, so the functions and methods in it become available to the parser as if they were handlers (just that they can return pointers and you might have to manage memory handed into or returned from them). See Also LEOParserGetHandlerNoteAtIndexvoid LEOParserGetHandlerNoteAtIndex( size_t inIndex, const char **outHandlerName, const char **outNote ); DiscussionScripts may contain notes (=documentation comments) above every handler definition. Use this function to access the list of notes that were found while parsing your script. LEOParserGetLastErrorLineNumsize_t LEOParserGetLastErrorLineNum( void ); DiscussionYou may call this after a call to LEOParserGetLastErrorMessage to determine the line in the script an error occurred on. If this returns SIZE_T_MAX, no line number information is available. See Also LEOParserGetLastErrorMessageconst char* LEOParserGetLastErrorMessage( void ); DiscussionCall this after each call to LEOParseTreeCreateFromUTF8Characters, LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters and LEOScriptCompileAndAddParseTree to detect errors. If it returns NULL, everything was fine. See Also LEOParserGetLastErrorOffsetsize_t LEOParserGetLastErrorOffset( void ); DiscussionYou may call this after a call to LEOParserGetLastErrorMessage to determine the character offset in the script an error occurred on. If this returns SIZE_T_MAX, no offset is available. Character offset information is usually only available for errors that happen early on in parsing. If you can't get an offset, you may want to try calling LEOParserGetLastErrorLineNum, which will often still at least be able to give you the line number for an error. See Also LEOParserGetNonFatalErrorMessageAtIndexvoid LEOParserGetNonFatalErrorMessageAtIndex( size_t inIndex, const char **outErrMsg, size_t *outLineNum, size_t *outOffset ); DiscussionThe Forge parser tries to behave very lenient regarding errors. So often, when it encounters a parse error, it will simply generate a PARSE_ERROR_INSTR instruction and abort the current handler, trying to find the next handler in the script. That way, if you have an error in a mouseDown handler, your mouseUp handler will still execute. This function gets an error from this list of non-fatal errors, so the host can e.g. show them as annotations on lines in the script editor, or in a project-wide "things to fix" window. LEOParseTreeCreateForCommandOrExpressionFromUTF8CharactersLEOParseTree* LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters( const char *inCode, size_t codeLength, uint16_t inFileID ); DiscussionCreate an abstract syntax tree from the given program fragment specified by inCode and codeLength. You can then call LEOScriptCompileAndAddParseTree to fill a LEOScript with the corresponding byte code. This can be used for evaluating a few commands, for example in the message box. Once you are done with the parse tree, call LEOCleanUpParseTree to free the memory associated with it. Provide a file name (or other unique display name that debuggers should show to the user on script errors) for inFileID by calling LEOFileIDForFileName. If you want to parse a complete script, use LEOParseTreeCreateFromUTF8Characters.: See Also LEOParseTreeCreateFromUTF8CharactersLEOParseTree* LEOParseTreeCreateFromUTF8Characters( const char *inCode, size_t codeLength, uint16_t inFileID ); DiscussionCreate an abstract syntax tree from the given script text specified by inCode and codeLength. You can then call LEOScriptCompileAndAddParseTree to fill a LEOScript with the corresponding byte code. Once you are done with the parse tree, call LEOCleanUpParseTree to free the memory associated with it. Provide a file name (or other unique display name that debuggers should show to the user on script errors) for inFileID by calling LEOFileIDForFileName. See Also LEOScriptCompileAndAddParseTreevoid LEOScriptCompileAndAddParseTree( LEOScript *inScript, LEOContextGroup *inGroup, LEOParseTree *inTree, uint16_t inFileID ); DiscussionTake a parse tree created by LEOParseTreeCreateFromUTF8Characters or LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters and compile it into Leonie bytecode. The given script, inScript will be filled with the command and function handlers, strings etc. defined in the script. Handler IDs will be generated in the given context group. Provide the same file ID in inFileID that you generated using LEOFileIDForFileName when you created the parse tree. See Also LEOSetFirstNativeCallCallbackvoid LEOSetFirstNativeCallCallback( LEOFirstNativeCallCallbackPtr inCallback ); DiscussionSince loading the headers for 'native calls' (i.e. native operating system APIs as you would call them from C, Objective C, C# or Pascal) may take a while, this callback is provided, which gets called the first time Forge needs to parse a native call, so you can lazily load the headers only when a script actually uses native calls and not incur the overhead otherwise. See Also TypedefsLEOParseTreetypedef struct LEOParseTree LEOParseTree; DiscussionLEOParseTree is a private, internal data structure representing a parse tree, i.e. it is a representation of a script's code in a more easily machine processible form than plain text. Internally it is equivalent to the CParseTree C++ class, but do not rely on that from your host application. |