Forge

Includes:
"LEOScript.h"
"LEOContextGroup.h"
"LEOValue.h"
"LEOInterpreter.h"
"LEOInstructions.h"
"LEODebugger.h"
"LEORemoteDebugger.h"
"LEOChunks.h"
"LEOContextGroup.h"
"LEOHandlerID.h"
"LEOPropertyInstructions.h"
"LEODownloadInstructions.h"
"LEOObjCCallInstructions.h"

Introduction

This 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

LEOAddBuiltInFunctionsAndOffsetInstructions
LEOAddBuiltInVariables
LEOAddGlobalPropertiesAndOffsetInstructions
LEOAddHostCommandsAndOffsetInstructions
LEOAddHostFunctionsAndOffsetInstructions
LEOAddNumberConstants
LEOAddOperatorsAndOffsetInstructions
LEOAddStringConstants
LEOAddUnaryOperatorsAndOffsetInstructions
LEOCleanUpDisplayInfoTable
LEOCleanUpParseTree
LEODebugPrintParseTree
LEODisplayInfoTableApplyToText
LEODisplayInfoTableCreateForParseTree
LEODisplayInfoTableGetHandlerInfoAtIndex
LEOLoadNativeHeadersFromFile
LEOParserGetHandlerNoteAtIndex
LEOParserGetLastErrorLineNum
LEOParserGetLastErrorMessage
LEOParserGetLastErrorOffset
LEOParserGetNonFatalErrorMessageAtIndex
LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters
LEOParseTreeCreateFromUTF8Characters
LEOScriptCompileAndAddParseTree
LEOSetFirstNativeCallCallback

LEOAddBuiltInFunctionsAndOffsetInstructions


void LEOAddBuiltInFunctionsAndOffsetInstructions(
    struct TBuiltInFunctionEntry *inEntries,
    size_t firstBuiltInFunctionInstruction );  
Discussion

Register 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.


LEOAddBuiltInVariables


void LEOAddBuiltInVariables(
    struct TBuiltInVariableEntry *inEntries );  
Discussion

Add 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".


LEOAddGlobalPropertiesAndOffsetInstructions


void LEOAddGlobalPropertiesAndOffsetInstructions(
    struct TGlobalPropertyEntry *inEntries,
    size_t firstGlobalPropertyInstruction );  
Discussion

Register 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.


LEOAddHostCommandsAndOffsetInstructions


void LEOAddHostCommandsAndOffsetInstructions(
    struct THostCommandEntry *inEntries,
    size_t firstHostCommandInstruction );  
Discussion

Register 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.


LEOAddHostFunctionsAndOffsetInstructions


void LEOAddHostFunctionsAndOffsetInstructions(
    struct THostCommandEntry *inEntries,
    size_t firstHostCommandInstruction );  
Discussion

Register 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.


LEOAddNumberConstants


void LEOAddNumberConstants(
    struct TNumberConstantEntry *inEntries );  
Discussion

Add one or more numeric constants to the table of Forge's built-in constants.

See Also


LEOAddOperatorsAndOffsetInstructions


void LEOAddOperatorsAndOffsetInstructions(
    struct TOperatorEntry *inEntries,
    size_t firstOperatorInstruction );  
Discussion

Register 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)


LEOAddStringConstants


void LEOAddStringConstants(
    struct TStringConstantEntry *inEntries );  
Discussion

Add one or more string constants to the table of Forge's built-in constants.

See Also


LEOAddUnaryOperatorsAndOffsetInstructions


void LEOAddUnaryOperatorsAndOffsetInstructions(
    struct TUnaryOperatorEntry *inEntries,
    size_t firstUnaryOperatorInstruction );  
Discussion

Register 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)


LEOCleanUpDisplayInfoTable


void LEOCleanUpDisplayInfoTable(
    LEODisplayInfoTable *inTable );  
Discussion

Free the memory occupied by this display info table.

See Also


LEOCleanUpParseTree


Discussion

Free the memory for a parse tree created by LEOParseTreeCreateFromUTF8Characters or LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters.

See Also


LEODebugPrintParseTree


Discussion

Print a description of a particular parse tree to the console, to help in debugging the engine.


LEODisplayInfoTableApplyToText


void LEODisplayInfoTableApplyToText(
    LEODisplayInfoTable *inTable,
    const char *code,
    size_t codeLen,
    char **outText,
    size_t *outLength,
    size_t *ioCursorPosition,
    size_t *ioCursorEndPosition );  
Parameters
inTable

A display info table created from a parse tree for the same text as provided in the code pointer.

code

The script to be indented.

codeLen

The length of text in code, not including any terminating NUL character it may have. The script text may contain NUL characters, which will be treated as regular characters.

outText

A block of text of length outLength +1. The additional character is a NUL character that is added for the caller's convenience. Treating a script as a C-string is not recommended, as scripts may contain user-entered NUL characters. The returned text block is created using malloc() and it is the caller's responsibility to call free() on it when done.

outLength

The number of actual text (exclusing the terminating NUL character) in outText.

ioCursorPosition

On input, the current offset of the text insertion mark in the script. On output, this will have been adjusted for any added/removed characters, so it stays in the same place as far as the user is concerned. You can pass NULL here if you don't need it.

ioCursorEndPosition

Same as ioCursorEndPosition, intended for holding the end of a selection range.

Discussion

Reformat 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


LEODisplayInfoTableCreateForParseTree


LEODisplayInfoTable* LEODisplayInfoTableCreateForParseTree(
    LEOParseTree *inTree );  
Discussion

Extract 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


LEODisplayInfoTableGetHandlerInfoAtIndex


void LEODisplayInfoTableGetHandlerInfoAtIndex(
    LEODisplayInfoTable *inTable,
    size_t inIndex,
    const char **outName,
    size_t *outLine,
    bool *outIsHandlerEnd,
    bool *outIsCommand );  
Discussion

Return 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


LEOLoadNativeHeadersFromFile


void LEOLoadNativeHeadersFromFile(
    const char *filepath );  
Discussion

Load 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


LEOParserGetHandlerNoteAtIndex


void LEOParserGetHandlerNoteAtIndex(
    size_t inIndex,
    const char **outHandlerName,
    const char **outNote );  
Discussion

Scripts 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.


LEOParserGetLastErrorLineNum


Discussion

You 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


LEOParserGetLastErrorMessage


const char* LEOParserGetLastErrorMessage(
    void );  
Discussion

Call this after each call to LEOParseTreeCreateFromUTF8Characters, LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters and LEOScriptCompileAndAddParseTree to detect errors. If it returns NULL, everything was fine.

See Also


LEOParserGetLastErrorOffset


size_t LEOParserGetLastErrorOffset(
    void );  
Discussion

You 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


LEOParserGetNonFatalErrorMessageAtIndex


void LEOParserGetNonFatalErrorMessageAtIndex(
    size_t inIndex,
    const char **outErrMsg,
    size_t *outLineNum,
    size_t *outOffset );  
Discussion

The 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.


LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters


LEOParseTree* LEOParseTreeCreateForCommandOrExpressionFromUTF8Characters(
    const char *inCode,
    size_t codeLength,
    uint16_t inFileID );  
Discussion

Create 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


LEOParseTreeCreateFromUTF8Characters


LEOParseTree* LEOParseTreeCreateFromUTF8Characters(
    const char *inCode,
    size_t codeLength,
    uint16_t inFileID );  
Discussion

Create 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


LEOScriptCompileAndAddParseTree


void LEOScriptCompileAndAddParseTree(
    LEOScript *inScript,
    LEOContextGroup *inGroup,
    LEOParseTree *inTree,
    uint16_t inFileID );  
Discussion

Take 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


LEOSetFirstNativeCallCallback


void LEOSetFirstNativeCallCallback(
    LEOFirstNativeCallCallbackPtr inCallback );  
Discussion

Since 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


Typedefs

LEOParseTree

LEOParseTree


typedef struct LEOParseTree LEOParseTree;  
Discussion

LEOParseTree 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.