Enhanced C#
Language of your choice: library documentation
Properties | Public Member Functions | List of all members
Loyc.LLParserGenerator.IPGCodeGenHelper Interface Reference

A class that implements this interface will generate small bits of code that the parser generator will use. The default implementation is IntStreamCodeGenHelper. To install a new code generator, set the LLParserGenerator.CodeGenHelper property or supply the generator in the constructor of LLParserGenerator. More...


Source file:
Inheritance diagram for Loyc.LLParserGenerator.IPGCodeGenHelper:
Loyc.LLParserGenerator.CodeGenHelperBase Loyc.LLParserGenerator.GeneralCodeGenHelper Loyc.LLParserGenerator.IntStreamCodeGenHelper

Remarks

A class that implements this interface will generate small bits of code that the parser generator will use. The default implementation is IntStreamCodeGenHelper. To install a new code generator, set the LLParserGenerator.CodeGenHelper property or supply the generator in the constructor of LLParserGenerator.

Two of these methods (VisitInput and FromCode) are called by the LLLPG macro. All the others are called by the main engine and its helper classes in LLParserGenerator.

Note that some parts of the code (the outer skeleton–if, while, for statements) are still generated by LLParserGenerator.GenerateCodeVisitor.

Properties

IPGTerminalSet EmptySet [get]
 Returns an empty set of the appropriate type for the kind of parser being generated by this code. More...
 

Public Member Functions

LNode VisitInput (LNode stmt, IMessageSink sink)
 In case the IPGCodeGenHelper is interested, the LLLPG macro calls this method on each statement in the body of the macro (as a preprocessing step, before LLLPG looks at it). No action is required. More...
 
Pred CodeToTerminalPred (LNode expr, ref string errorMsg)
 Creates a terminal predicate from a code expression. More...
 
IPGTerminalSet Optimize (IPGTerminalSet set, IPGTerminalSet dontcare)
 Simplifies the specified set, if possible, so that GenerateTest() can generate simpler code for an if-else chain in a prediction tree. More...
 
char? ExampleChar (IPGTerminalSet set)
 Returns an example of a character in the set, or null if this is not a set of characters or if EOF is the only member of the set. More...
 
string Example (IPGTerminalSet set)
 Returns an example of an item in the set. If the example is a character, it should be surrounded by single quotes. More...
 
void Begin (WList< LNode > classBody, ISourceFile sourceFile)
 Before the parser generator generates code, it calls this method. More...
 
void BeginRule (Rule rule)
 Notifies the snippet generator that code generation is starting for a new rule. More...
 
void Done ()
 LLParserGenerator calls this method to notify the snippet generator that code generation is complete. More...
 
LNode TerminalType [get]
 Type of variables auto-declared when you use labels in your grammar (e.g. x:Foo (list+:Bar)*) More...
 
LNode GenerateSkip (bool savingResult)
 Generate code to match any token. More...
 
LNode GenerateAndPredCheck (AndPred andPred, LNode code, int lookaheadAmt)
 Generate code to check an and-predicate during or after prediction, e.g. &!{foo} becomes !(foo) during prediction and Check(!(foo)); afterward. More...
 
LNode GenerateMatch (IPGTerminalSet set_, bool savingResult, bool recognizerMode)
 Generate code to match a set, e.g. MatchRange('a', 'z'); or MatchExcept('
', '\r'); }
. If the set is too complex, a declaration for it is created in the classBody which was passed to Begin(). More...
 
LNode LA (int k)
 Generates code to read LA(k). More...
 
LNode LAType ()
 Returns the data type of LA(k) More...
 
LNode ErrorBranch (IPGTerminalSet covered, int laIndex)
 Generates code for the error branch of prediction. More...
 
bool ShouldGenerateSwitch (IPGTerminalSet[] branchSets, MSet< int > casesToInclude, bool hasErrorBranch)
 Returns true if a "switch" statement is the preferable code generation technique rather than the default if-else chain More...
 
LNode GenerateSwitch (IPGTerminalSet[] branchSets, LNode[] branchCode, MSet< int > casesToInclude, LNode defaultBranch, LNode laVar)
 Generates a switch statement with the specified branches where branchCode[i] is the code to run if the input is in the set branchSets[i]. More...
 
LNode GenerateTest (IPGTerminalSet set, LNode laVar)
 Generates code to test whether the terminal denoted 'laVar' is in the set. More...
 
LNode CreateRuleMethod (Rule rule, LNodeList methodBody)
 Generates the method for a rule, given the method's contents. More...
 
LNode CreateTryWrapperForRecognizer (Rule rule)
 Generates the try-wrapper for a recognizer rule. More...
 
LNode CallRule (RuleRef rref, bool recognizerMode)
 Generates code to call a rule based on rref.Rule.Name and rref.Params. More...
 
LNode CallTryRecognizer (RuleRef rref, int lookahead)
 Generates a call to the Try_Scan_*() function that wraps around a Scan_*() recognizer. Called while generating code for an and-pred. More...
 
LNode GetListType (LNode type)
 Gets the list type for elements of the specified type (e.g. List<type>) More...
 
LNode MakeInitializedVarDecl (LNode type, bool wantList, Symbol varName)
 Gets a variable declaration for the specified type, e.g. if type is Foo and wantList == true and varName.Name == "x", the statement returned might be List<Foo> x = new List<Foo>(); More...
 
LNode ResolveAlias (LNode node)
 Returns the node for an alias. If the specified node is not an alias, returns the same node unchanged. More...
 

Member Function Documentation

◆ Begin()

void Loyc.LLParserGenerator.IPGCodeGenHelper.Begin ( WList< LNode classBody,
ISourceFile  sourceFile 
)

Before the parser generator generates code, it calls this method.

Parameters
classBodythe body (braced block) of the class where the code will be generated, which allows the snippet generator to add code at class level when needed.
sourceFilethe suggested ISourceFile to assign to generated code snippets.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

Referenced by Loyc.LLParserGenerator.LLParserGenerator.Run().

◆ BeginRule()

void Loyc.LLParserGenerator.IPGCodeGenHelper.BeginRule ( Rule  rule)

Notifies the snippet generator that code generation is starting for a new rule.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ CallRule()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.CallRule ( RuleRef  rref,
bool  recognizerMode 
)

Generates code to call a rule based on rref.Rule.Name and rref.Params.

Returns

For a normal rule call, this method should return rref.AutoSaveResult(code) where code is the code to invoke the rule.

Recognizer mode is normally implemented by calling the recognizer version of the rule in an "if" statement: if (!Scan_Foo()) return false;

Backtrack mode expects a boolean expression to be returned, normally something like Try_Scan_Foo() where the name Try_Is_Foo comes from the recognizer's Rule.TryWrapperName.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ CallTryRecognizer()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.CallTryRecognizer ( RuleRef  rref,
int  lookahead 
)

Generates a call to the Try_Scan_*() function that wraps around a Scan_*() recognizer. Called while generating code for an and-pred.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ CodeToTerminalPred()

Pred Loyc.LLParserGenerator.IPGCodeGenHelper.CodeToTerminalPred ( LNode  expr,
ref string  errorMsg 
)

Creates a terminal predicate from a code expression.

Parameters
exprA expression provided by the user, such as "a string", a Token.Type, or a value..range. expr will not be a call to the inversion operator #~ (that's handled internally using IPGTerminalSet.Inverted()). This method also handles the "any token" input, which is an underscore by convention (_).
errorMsgAn error message to display. If the method returns null, the LLLPG macro shows this as an error; if this method does not return null, the message (if provided) is shown as a warning.
Returns
If successful, a terminal predicate; otherwise null.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase, Loyc.LLParserGenerator.GeneralCodeGenHelper, and Loyc.LLParserGenerator.IntStreamCodeGenHelper.

◆ CreateRuleMethod()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.CreateRuleMethod ( Rule  rule,
LNodeList  methodBody 
)

Generates the method for a rule, given the method's contents.

Parameters
ruleRule for which a method is needed.
methodBodyA list of statements produced by LLParserGenerator inside the method.
Returns
A method definition for the rule.

To generate the default method, simply call Rule.CreateMethod(VList<LNode>).

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ CreateTryWrapperForRecognizer()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.CreateTryWrapperForRecognizer ( Rule  rule)

Generates the try-wrapper for a recognizer rule.

To generate the default method, simply call rule.CreateTryWrapperForRecognizer().

Recognizers consist of two methods: the recognizer itself and the try-wrapper, if it is needed by the grammar. For example, the recognizer version of this rule:

rule Hello "hi" { <em>foo++; } };

is this pair of methods:

bool Try_Scan_Hello() {
using (new SavedPosition(this))
return Scan_Hello();
}
bool Scan_Hello() {
if (!TryMatch('h'))
return false;
if (!TryMatch('i'))
return false;
return true;
}

The Try* helper method is called from normal rules that use an zero-width assertion (&Hello), while the recognizer method Scan_* is called from other recognizers that call the rule normally (i.e. NOT using an and-predicate). By the way, the LLLPG core removes actions like _foo++ from the recognizer version.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ Done()

void Loyc.LLParserGenerator.IPGCodeGenHelper.Done ( )

LLParserGenerator calls this method to notify the snippet generator that code generation is complete.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

Referenced by Loyc.LLParserGenerator.LLParserGenerator.Run().

◆ ErrorBranch()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.ErrorBranch ( IPGTerminalSet  covered,
int  laIndex 
)

Generates code for the error branch of prediction.

Parameters
coveredThe permitted token set, which the input did not match. NOTE: if the input matched but there were and-predicates that did not match, this parameter will be null (e.g. the input is 'b' in (&{x} 'a' | &{y} 'b'), but y is false).
laIndexLookahead amount at which the error branch is being created.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ Example()

string Loyc.LLParserGenerator.IPGCodeGenHelper.Example ( IPGTerminalSet  set)

Returns an example of an item in the set. If the example is a character, it should be surrounded by single quotes.

This helps produce error messages in LLLPG.

Implemented in Loyc.LLParserGenerator.IntStreamCodeGenHelper, Loyc.LLParserGenerator.GeneralCodeGenHelper, and Loyc.LLParserGenerator.CodeGenHelperBase.

◆ ExampleChar()

char? Loyc.LLParserGenerator.IPGCodeGenHelper.ExampleChar ( IPGTerminalSet  set)

Returns an example of a character in the set, or null if this is not a set of characters or if EOF is the only member of the set.

This helps produce error messages in LLLPG.

Implemented in Loyc.LLParserGenerator.IntStreamCodeGenHelper, and Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GenerateAndPredCheck()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GenerateAndPredCheck ( AndPred  andPred,
LNode  code,
int  lookaheadAmt 
)

Generate code to check an and-predicate during or after prediction, e.g. &!{foo} becomes !(foo) during prediction and Check(!(foo)); afterward.

Parameters
andPredPredicate for which an expression has already been generated
codeThe expression to be checked
lookaheadAmtCurrent lookahead amount. -1 means "prediction is complete, generate a Check() statement".

LLLPG substitutes $LI and $LA before it calls this method.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GenerateMatch()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GenerateMatch ( IPGTerminalSet  set_,
bool  savingResult,
bool  recognizerMode 
)

Generate code to match a set, e.g. MatchRange('a', 'z'); or MatchExcept('
', '\r'); }
. If the set is too complex, a declaration for it is created in the classBody which was passed to Begin().

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GenerateSkip()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GenerateSkip ( bool  savingResult)

Generate code to match any token.

Returns
Default implementation returns Skip(); }, or MatchAny(); } if the result is to be saved.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GenerateSwitch()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GenerateSwitch ( IPGTerminalSet[]  branchSets,
LNode[]  branchCode,
MSet< int >  casesToInclude,
LNode  defaultBranch,
LNode  laVar 
)

Generates a switch statement with the specified branches where branchCode[i] is the code to run if the input is in the set branchSets[i].

Parameters
casesToIncludeThe set chosen by ShouldGenerateSwitch.
defaultBranchCode to be placed in the default: case, or the empty identifier (@``) if none
laVarThe lookahead variable being switched on (e.g. la0)
Returns
The generated switch block.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GenerateTest()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GenerateTest ( IPGTerminalSet  set,
LNode  laVar 
)

Generates code to test whether the terminal denoted 'laVar' is in the set.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ GetListType()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.GetListType ( LNode  type)

Gets the list type for elements of the specified type (e.g. List<type>)

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ LA()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.LA ( int  k)

Generates code to read LA(k).

Returns
The default implementation returns @(LA(k)).

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase, and Loyc.LLParserGenerator.GeneralCodeGenHelper.

◆ LAType()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.LAType ( )

Returns the data type of LA(k)

Returns
The default implementation returns @(int).

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase, Loyc.LLParserGenerator.GeneralCodeGenHelper, and Loyc.LLParserGenerator.IntStreamCodeGenHelper.

◆ MakeInitializedVarDecl()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.MakeInitializedVarDecl ( LNode  type,
bool  wantList,
Symbol  varName 
)

Gets a variable declaration for the specified type, e.g. if type is Foo and wantList == true and varName.Name == "x", the statement returned might be List<Foo> x = new List<Foo>();

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ Optimize()

IPGTerminalSet Loyc.LLParserGenerator.IPGCodeGenHelper.Optimize ( IPGTerminalSet  set,
IPGTerminalSet  dontcare 
)

Simplifies the specified set, if possible, so that GenerateTest() can generate simpler code for an if-else chain in a prediction tree.

Parameters
set
dontcareA set of terminals that have been ruled out, i.e. it is already known that the lookahead value is not in this set.
Returns
An optimized set, or this.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase, and Loyc.LLParserGenerator.IntStreamCodeGenHelper.

◆ ResolveAlias()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.ResolveAlias ( LNode  node)

Returns the node for an alias. If the specified node is not an alias, returns the same node unchanged.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ ShouldGenerateSwitch()

bool Loyc.LLParserGenerator.IPGCodeGenHelper.ShouldGenerateSwitch ( IPGTerminalSet[]  branchSets,
MSet< int >  casesToInclude,
bool  hasErrorBranch 
)

Returns true if a "switch" statement is the preferable code generation technique rather than the default if-else chain

Parameters
branchSetsNon-overlapping terminal sets, one set for each branch of the prediction tree.
casesToIncludeTo this set, this method should add the indexes of branches for which case labels should be generated, e.g. adding index 2 means that switch cases should be generated for sets[2]. The caller (LLParserGenerator) will create an if-else chain for all branches that are not added to casesToInclude, and this chain will be passed to GenerateSwitch.

Using a switch() statement can be important for performance, since the compiler may be able to implement a switch statement using as little as a single branch, unlike an if-else chain which often requires multiple branches.

However, it does not always make sense to use switch(), and when it does make sense, it may not be wise or possible to include all cases in the switch, so this method is needed to make the decision.

Consider an example with four branches, each having a character set, plus an error branch:

    Branch 1: '*'|'+'|'-'|'/'|''|'^'|'&'|','|'|'
    Branch 2: '_'|'$'|'a'..'z'|'A'..'Z'|128..65535
    Branch 3: '0'..'9'
    Branch 4: ' '|'\t'
    Error: anything else

In this case, it is impossible (well, quite impractical) to use cases for all of Branch 2. The most sensible switch() statement probably looks like this:

    switch(la0) {
    case '*': case '+': case '-': case '/': case '':
    case '^': case '&': case ',': case '|':
        // branch 1
    case '0': case '1': case '2': case '3': case '4': 
    case '5': case '6': case '7': case '8': case '9': 
        // branch 3
    case ' ': case '\t':
        // branch 4
    default:
        if (la0 >= 'A' && la0 <= 'Z' || la0 >= 'a' && la0 <= 'z' || la0 >= 128 && la0 <= 65536)
            // branch 2
        else
            // error
    }

Please note that given LLLPG's current design, it is not possible to "split" a branch. For example, the switch cannot include "case '_': case '$':" and use this to handle branch 2 (but not the error case), while also handling branch 2 in the "default" case. Although LLLPG has a mechanism to duplicate branches of an Alts so that the code for handling an alternative is located at two different places in a prediction tree (using 'goto' if necessary), it does not have a similar mechanism for arbitrary subtrees of a prediction tree.

'sets' does not include the error branch, if any. If there's no error branch, the last case should be left out of 'casesToInclude' so that there will be a 'default:' case. Note: it should always be the last set that is left out, because that will be the official default branch (the user can control which branch is default, hence which one comes last, using the 'default' keyword in the grammar DSL.)

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

◆ VisitInput()

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.VisitInput ( LNode  stmt,
IMessageSink  sink 
)

In case the IPGCodeGenHelper is interested, the LLLPG macro calls this method on each statement in the body of the macro (as a preprocessing step, before LLLPG looks at it). No action is required.

Returns
a new statement to replace the original statement, or null to do nothing.

Implemented in Loyc.LLParserGenerator.CodeGenHelperBase.

Property Documentation

◆ EmptySet

IPGTerminalSet Loyc.LLParserGenerator.IPGCodeGenHelper.EmptySet
get

Returns an empty set of the appropriate type for the kind of parser being generated by this code.

◆ TerminalType

LNode Loyc.LLParserGenerator.IPGCodeGenHelper.TerminalType
get

Type of variables auto-declared when you use labels in your grammar (e.g. x:Foo (list+:Bar)*)