public class Analyzer extends Utility
collection of modules or a single module. In
particular, it provides:
init(Grammar) and accessed through lookup(String) and lookup(ModuleName). After
initialization, the grammar can be accessed through grammar().init(Grammar) or init(Module) and accessed through lookup(NonTerminal),
lookup(NonTerminal,Module), and lookupGlobally(NonTerminal). When initializing this mapping
through a grammar, relative look ups
can only be performed within the context of processing a module. Note that the mapping contains both
qualified and unqualified names.test for and access the top-level (or root) module of a grammar.add and remove modules. These methods update both the mapping from module
names to modules and from nonterminals to productions, but they do
not update the current grammar.test whether a
module is imported by another, to trace a module's
dependencies, and to test
whether a module or any of its dependencies has a specified
attribute.test whether a
production is defined by a module and to test whether a production is
imported by a module.processing a module
and to determine the current module;
additionally, methods to switch to a
different module and switch back again when
processing productions from several modules.uniquify() the names of all
productions across all modules.processing a
production and to determine the current
production.workingOn(NonTerminal), notWorkingOn(NonTerminal), notWorkingOnAny(), isBeingWorkedOn(NonTerminal), and working(). The marked
set is accessed through mark(NonTerminal), mark(Collection), markAll(), unmark(NonTerminal), unmarkAll(), hasMarked(),
isMarked(NonTerminal), and marked(). Finally,
the processed set is accessed through clearProcessed(),
processed(NonTerminal), and isProcessed(NonTerminal). Note that all nonterminals used in
these sets should be fully qualified.add(FullProduction) and committed to the grammar through addNewProductionsAt(int). Existing productions are removed
through remove(FullProduction).variable(), split(), choice(), star(), plus(),
option(), tail(), and shared(). Also, a
method to test whether a given variable or nonterminal is
synthetic. Besides shared variables, synthetic variables can only
be created while processing a
production.strip unnecessary ordered
choices and sequences from an element and a method to strip only ordered choices.copy an element.hasTerminalPrefix(Sequence), normalizeTerminals(Sequence), and joinTerminals(Sequence,Element).haveCommonPrefix(Sequence,Sequence), normalizePrefix(Sequence,Sequence), and joinPrefixes(Sequence,Element).get the text of an
element.restricts the input.consumes the input.matches the empty input.relies only on not-followed-by
predicates.can be
bound, a method to add a binding to a list of
elements, a method to access the only
binding in a list of elements, and methods to unbind and strip
and unbind an element.get a list's
value.an element or a list sets the semantic value, either
through a binding, semantic action, or value element. Another
method to determine whether a list
sets the semantic value to null.may be null.type an element.a grammar or a module
and the visitor must be registered. When
processing modules in a grammar, this utility must be notified. When processing productions, this
utility must also be notified.
The analyzer utility tracks the current grammar or module so
that it need not recreate its internal state as long as the same
analyzer utility is used across different visitors.| Modifier and Type | Field and Description |
|---|---|
static java.lang.String |
CHOICE
The suffix for nonterminals representing choices.
|
protected int |
choiceCount
The count of lifted choices for the current production.
|
static java.lang.String |
DUMMY
The name for dummy variables (in case of errors).
|
protected Grammar |
grammar
The grammar.
|
protected java.util.Map<NonTerminal,java.lang.Object> |
grammarPMap
The grammar-wide map from nonterminals to productions.
|
protected boolean |
isGrammarMode
Flag for whether we are processing a grammar or a module.
|
static int |
MAX_COUNT
The maximum character count for turning character classes into
character switches.
|
protected Module |
mCurrent
The current grammar module.
|
protected Module |
module
The self-contained grammar module.
|
protected java.util.Map<java.lang.String,Module> |
moduleMap
The map from module names (as strings) to module objects.
|
static java.lang.String |
OPTION
The suffix for nonterminals representing options.
|
protected int |
optionCount
The count of desugared options for the current production.
|
protected Production |
pCurrent
The current production.
|
static java.lang.String |
PLUS
The suffix for nonterminals representing one or more
repetitions.
|
protected int |
plusCount
The count of desugared plus repetitions for the current production.
|
protected java.util.Map<NonTerminal,FullProduction> |
pMap
The map from nonterminals to productions for the current module.
|
protected java.util.Set<NonTerminal> |
pMarked
The set of nonterminals corresponding to productions having
been marked.
|
protected java.util.List<Production> |
pNew
The list of newly added productions.
|
protected java.util.Set<NonTerminal> |
pProcessed
The set of nonterminals corresponding to productions having
been processed.
|
protected java.util.Set<NonTerminal> |
pWorking
The set of nonterminals corresponding to productions currently
being processed.
|
static java.lang.String |
SEPARATOR
The separator character for creating new nonterminals, which
should be illegal in regular variable or nonterminal names.
|
static java.lang.String |
SHARED
The base name for nonterminals representing shared productions.
|
protected int |
sharedCount
The count of shared productions.
|
static java.lang.String |
SPLIT
The suffix for nonterminals representing split alternatives.
|
protected int |
splitCount
The count of splits for the current production.
|
static java.lang.String |
STAR
The suffix for nonterminals representing zero or more
repetitions.
|
protected int |
starCount
The count of desugared star repetitions for the current production.
|
static java.lang.String |
TAIL
The suffix for nonterminals representing tail productions.
|
protected int |
tailCount
The count of tail productions for the current production.
|
protected int |
varCount
The count of synthetic variables for the current production.
|
static java.lang.String |
VARIABLE
The base name for synthetic variables.
|
protected Copier |
xerox
The element copier.
|
| Constructor and Description |
|---|
Analyzer()
Create a new analyzer utility.
|
| Modifier and Type | Method and Description |
|---|---|
void |
add(FullProduction p)
Prepare the specified production for addition to the grammar
module.
|
void |
add(Module m)
Add the specified module to the current grammar.
|
int |
addNewProductionsAt(int idx)
Add the newly generated productions to the grammar itself.
|
Binding |
bind(java.util.List<Element> l)
Bind the elements in the specified list.
|
Binding |
bind(java.util.List<Element> l,
java.lang.String marker)
Bind the elements in the specified list.
|
NonTerminal |
choice()
Create a new nonterminal for a choice.
|
void |
clearProcessed()
Clear the processed status of all nonterminals.
|
boolean |
consumesInput(Element e)
Determine whether the specified element may consume the input.
|
Module |
copy(Module m)
Make a deep copy of the specified module.
|
<T extends Element> |
copy(T e)
Make a deep copy of the specified element.
|
Production |
current()
Get the production currently being processed.
|
Module |
currentModule()
Get the module currently being processed.
|
java.lang.Object |
enter(Production p)
Enter the specified production.
|
void |
exit(java.lang.Object closure)
Exit a previously entered production.
|
static Binding |
getBinding(java.util.List<Element> l)
Get the binding for the specified list's value.
|
Element |
getValue(java.util.List<Element> list,
boolean ignoreActions)
Get the specified list's semantic value.
|
int |
getVarCount()
Get the current counter for synthetic variables.
|
Grammar |
grammar()
Get the initializing grammar.
|
boolean |
hasAttribute(Module m,
java.lang.String name,
java.util.Set<ModuleName> visited)
Determine whether the specified module or any of its import or
modification dependencies has an attribute with the specified
name.
|
boolean |
hasMarked()
Determine whether any nonterminals are marked.
|
boolean |
hasTerminalPrefix(Sequence s)
Determine whether the specified sequence starts with terminals
that can be optimized.
|
boolean |
haveCommonPrefix(Sequence s1,
Sequence s2)
Determine whether the specified sequences start with prefixes
that can be folded.
|
void |
init(Grammar g)
Initialize this analyzer for the specified grammar.
|
void |
init(Module m)
Initialize this analyzer for the specified module.
|
boolean |
isBeingWorkedOn(NonTerminal nt)
Determine whether the specified nonterminal is being worked on.
|
boolean |
isBindable(Element e)
Determine whether the specified element can be bound.
|
boolean |
isDefined(Production p,
Module m)
Determine whether the specified production is defined by the
specified module.
|
boolean |
isImported(Production p,
Module m)
Determine whether the specified production is defined by a module
imported by the specified module.
|
boolean |
isImported(java.lang.String name,
Module m)
Determine whether the module with the specified name is imported
by the specified module.
|
boolean |
isMarked(NonTerminal nt)
Determine whether the specified nonterminal has been marked.
|
boolean |
isNotFollowedBy(Element e)
Determine whether the specified element is a not-followed-by
predicate.
|
boolean |
isProcessed(NonTerminal nt)
Determine whether the specified nonterminal has been processed.
|
static boolean |
isSynthetic(NonTerminal nt)
Determine whether the specified nonterminal is synthetic.
|
static boolean |
isSynthetic(java.lang.String var)
Determine whether the specified variable is a synthetic variable.
|
boolean |
isTopLevel(Module m)
Determine whether the specified module is the top-level module.
|
Element |
joinPrefixes(Sequence source,
Element target)
Join the specified sequence with the specified element.
|
Element |
joinTerminals(Sequence source,
Element target)
Join the specified sequence with the specified element.
|
Module |
lookup(ModuleName module)
Look up the specified module.
|
FullProduction |
lookup(NonTerminal nt)
Look up the production for the specified nonterminal.
|
FullProduction |
lookup(NonTerminal nt,
Module m)
Look up the production for the specified nonterminal, which is
also defined by the specified module.
|
Module |
lookup(java.lang.String module)
Look up the specified module.
|
FullProduction |
lookupGlobally(NonTerminal nt)
Look up the production for the specified qualified nonterminal.
|
void |
mark(java.util.Collection<NonTerminal> nts)
Mark the specified nonterminals.
|
void |
mark(NonTerminal nt)
Mark the specified nonterminal.
|
void |
markAll()
Mark all of a grammar module's nonterminals.
|
java.util.Set<NonTerminal> |
marked()
Get the set of marked nonterminals.
|
boolean |
matchesEmpty(Element e)
Determine whether the specified element matches the empty input.
|
java.lang.String |
matchingText(Element e)
Get the text matched by the specified element.
|
boolean |
mayBeNull(Element element)
Determine whether the list value of the specified element may be
null. |
Module |
module()
Get the initializing module.
|
Sequence |
normalizePrefix(Sequence s1,
Sequence s2)
Normalize the specified sequences for
joining with other sequences
during prefix folding. |
Sequence |
normalizeTerminals(Sequence s)
Normalize the specified sequence for
joining with other elements
during terminal optimization. |
void |
notWorkingOn(NonTerminal nt)
Set the status of the specified nonterminal as not being worked
on.
|
void |
notWorkingOnAny()
Set the status of all nonterminals as not being worked on.
|
NonTerminal |
option()
Create a new nonterminal for an option.
|
NonTerminal |
plus()
Create a new nonterminal for one or more repetitions.
|
void |
process(Module m)
Process the specified module.
|
void |
process(Production p)
Process the specified production.
|
void |
processed(NonTerminal nt)
Set the status of the specified nonterminal as processed.
|
void |
remove(FullProduction p)
Prepare the specified production for removal from the grammar.
|
void |
remove(Module m)
Remove the specified module from the current grammar.
|
void |
reset()
Forcibly reset the analyzer utility.
|
void |
resetVarCount()
Reset the counter for synthetic variables.
|
boolean |
restrictsInput(Element e)
Determine whether the specified element restricts the input.
|
static boolean |
setsNullValue(java.util.List<Element> l)
Determine whether the specified list of elements sets the
semantic value to
null. |
static boolean |
setsValue(Element e,
boolean all)
Determine whether the specified element sets the semantic value.
|
static boolean |
setsValue(java.util.List<Element> l,
boolean all)
Determine whether the specified list of elements sets the
semantic value.
|
void |
setVarCount(int count)
Set the counter for synthetic variables.
|
NonTerminal |
shared()
Create a new nonterminal for a shared production.
|
NonTerminal |
split()
Create a new nonterminal for a split.
|
NonTerminal |
star()
Create a new nonterminal for zero or more repetitions.
|
void |
startAdding()
Clear the list of newly generated productions.
|
static Element |
strip(Element e)
Strip unnecessary ordered choices and sequences from the specified
element.
|
static Element |
stripAndUnbind(Element e)
Strip and unbind the specified element.
|
static OrderedChoice |
stripChoices(OrderedChoice c)
Strip unnecessary ordered choices from the specified choice.
|
NonTerminal |
tail()
Create a new nonterminal for a tail production.
|
Module |
topLevel()
Get the top-level module.
|
void |
trace(Module m,
java.util.Set<ModuleName> imports,
java.util.Map<ModuleName,java.lang.Boolean> modified)
Trace the specified module's dependencies.
|
Type |
type(Element element)
Type the specified element.
|
static Element |
unbind(Element e)
Unbind the specified element.
|
void |
uniquify()
Rename all productions to have unique names.
|
void |
unmark(NonTerminal nt)
Unmark the specified nonterminal.
|
void |
unmarkAll()
Unmark all nonterminals.
|
java.lang.String |
variable()
Create a new synthetic variable.
|
java.lang.String |
variable(java.lang.String marker)
Create a new synthetic variable with the specified marker.
|
java.util.Set<NonTerminal> |
working()
Get the set of nonterminals being worked on.
|
void |
workingOn(NonTerminal nt)
Set the status of the specified nonterminal as being worked on.
|
public static final java.lang.String SEPARATOR
public static final java.lang.String SHARED
public static final java.lang.String VARIABLE
public static final java.lang.String DUMMY
public static final java.lang.String SPLIT
public static final java.lang.String CHOICE
public static final java.lang.String STAR
public static final java.lang.String PLUS
public static final java.lang.String OPTION
public static final java.lang.String TAIL
public static final int MAX_COUNT
protected final Copier xerox
protected boolean isGrammarMode
protected Grammar grammar
protected java.util.Map<java.lang.String,Module> moduleMap
protected java.util.Map<NonTerminal,java.lang.Object> grammarPMap
protected Module mCurrent
protected Module module
protected java.util.Map<NonTerminal,FullProduction> pMap
protected Production pCurrent
protected java.util.Set<NonTerminal> pWorking
protected java.util.Set<NonTerminal> pMarked
protected java.util.Set<NonTerminal> pProcessed
protected java.util.List<Production> pNew
protected int varCount
protected int splitCount
protected int choiceCount
protected int starCount
protected int plusCount
protected int optionCount
protected int tailCount
protected int sharedCount
public void reset()
public void init(Grammar g)
qualified name field for each
production (if it has not been initialized). This method also
clears the sets of marked and processed nonterminals. It should
be called before iterating over the grammar's modules.g - The grammar.public boolean isImported(java.lang.String name,
Module m)
name - The module name.m - The depending module.true if the specified module (or any of the
modules modified by that module) imports the module with the
specified name.public void trace(Module m, java.util.Set<ModuleName> imports, java.util.Map<ModuleName,java.lang.Boolean> modified)
Boolean.TRUE if the module is modified more than
once. Otherwise, it is false. This method assumes that each
module modification's modification
field has been correctly initialized. Furthermore, the specified
set and map should be empty, with the exception of the set of
imported modules containing the name of the root module.m - The module.imports - The imported modules.modified - The modified modules.public boolean hasAttribute(Module m, java.lang.String name, java.util.Set<ModuleName> visited)
m - The module.name - The attribute name.visited - An empty helper set.true if the specified module or any of its
dependencies has the specified attribute.public void add(Module m)
list of modules.m - The module.java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.public void remove(Module m)
list of modules.m - The module.java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.public Grammar grammar()
java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.init(Grammar)public boolean isTopLevel(Module m)
m - The module.true if the specified module is the
top-level module.public Module topLevel()
public void init(Module m)
m - The self-contained module.public Module module()
java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a module.init(Module)public Module lookup(java.lang.String module)
module - The module name.null if there is
no such module.java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.public Module lookup(ModuleName module)
module - The module name.null if there is
no such module.java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.public FullProduction lookupGlobally(NonTerminal nt)
nt - The nonterminal.null if
there is no such production.public FullProduction lookup(NonTerminal nt, Module m)
nt - The nonterminalm - The module.null if the
specified module does not define a production with the
specified nonterminal.java.lang.IllegalArgumentException - Signals multiple definitions for the specified nonterminal.java.lang.IllegalStateException - Signals that this analyzer has not
been initialized with a grammar.public FullProduction lookup(NonTerminal nt)
process(Module) to correctly resolve
nonterminals.nt - The nonterminal.null
if there is no such production.java.lang.IllegalArgumentException - Signals that there are multiple, ambiguous productions.public boolean isDefined(Production p, Module m)
p - The production.m - The module.true if the production is defined by the
specified module.public boolean isImported(Production p, Module m)
p - The production.m - The module.true if the specified production is imported
by the specified module.public void uniquify()
grammar. Further note
that this method may change a production's name as well as the internal mapping from nonterminals to
productions. This method assumes that all partial productions
have been applied.public void process(Module m)
m - The module.public Module currentModule()
public java.lang.Object enter(Production p)
p - The production.exit(Object).public void exit(java.lang.Object closure)
enter(Production).closure - The closure returned from enter().public void process(Production p)
p - The production.public Production current()
public void workingOn(NonTerminal nt)
nt - The nonterminal.public void notWorkingOn(NonTerminal nt)
nt - The nonterminal.public void notWorkingOnAny()
public boolean isBeingWorkedOn(NonTerminal nt)
nt - The nonterminal.true if the nonterminal is being worked
on.public java.util.Set<NonTerminal> working()
process(xtc.parser.Module).public void mark(NonTerminal nt)
nt - The nonterminal.public void mark(java.util.Collection<NonTerminal> nts)
nts - The list of nonterminals.public void markAll()
public void unmark(NonTerminal nt)
nt - The nonterminal.public void unmarkAll()
public boolean hasMarked()
true if any nonterminal has been marked.public boolean isMarked(NonTerminal nt)
nt - The nonterminal.true if the nonterminal has been
marked.public java.util.Set<NonTerminal> marked()
public void clearProcessed()
public void processed(NonTerminal nt)
nt - The nonterminal.public boolean isProcessed(NonTerminal nt)
nt - The nonterminal.true if the nonterminal has been processed.public void startAdding()
add(FullProduction) and addNewProductionsAt(int).public void add(FullProduction p)
synthetic. However, addition is not
complete: the productions in the list of newly generated
productions still need to be added into the grammar itself. This
is typically done within the main loop iterating over a grammar's
productions and thus through a separate method.p - The new production.public int addNewProductionsAt(int idx)
add() into the current grammar at the
specified index of the grammar's list of productions.idx - The index into the grammar's list of productions.public void remove(FullProduction p)
p - The production.public void resetVarCount()
process(Production) already resets this counter; this method
provides more fine-grained control.public int getVarCount()
public void setVarCount(int count)
count - The new counter value.public java.lang.String variable()
public java.lang.String variable(java.lang.String marker)
marker - The marker.public static boolean isSynthetic(java.lang.String var)
var - The variable name.true if the specified variable name is
a synthetic variable returned by variable().public NonTerminal split()
public NonTerminal choice()
public NonTerminal star()
public NonTerminal plus()
public NonTerminal option()
public NonTerminal tail()
public NonTerminal shared()
public static boolean isSynthetic(NonTerminal nt)
nt - The nonterminal.true if the nonterminal is synthetic.public static Element strip(Element e)
e - The element.public static OrderedChoice stripChoices(OrderedChoice c)
c - The choice.public Module copy(Module m)
m - The module.public <T extends Element> T copy(T e)
e - The element.public boolean hasTerminalPrefix(Sequence s)
true if
the terminals can be optimized through character switches.
Currently, this is only the case for character and string
literals.s - The sequence.true if the sequence starts with optimizable
terminals.public Sequence normalizeTerminals(Sequence s)
joining with other elements
during terminal optimization. Currently, this method converts
string literals into equivalent subsequences of character
literals.s - The sequence.public Element joinTerminals(Sequence source, Element target)
normalized. Further note that the
combined element is guaranteed to either be a sequence or an
ordered choice.source - The source sequence.target - The target element.public boolean haveCommonPrefix(Sequence s1, Sequence s2)
s1 - The first sequence.s2 - The second sequence.true if the two sequences start with prefixes
that can be folded.public Sequence normalizePrefix(Sequence s1, Sequence s2)
joining with other sequences
during prefix folding. The first specified sequence should
always be the first sequence that has a common prefix with
sequences following in an ordered choice, while the second
specified sequence should iterate over the following sequences.s1 - The first sequence.s2 - The second sequence.public Element joinPrefixes(Sequence source, Element target)
normalized. Further note
that that the combined element is guaranteed to either be a
sequence or an ordered choice.source - The source sequence.target - The target element.public java.lang.String matchingText(Element e)
null. Note that this
method ignores predicates, actions, node markers, null literals,
and value elements, as they do not change the text matched by an
element. Further note that this method recursively analyzes
referenced nonterminals.e - The element.public boolean restrictsInput(Element e)
process() invocations must have been
performed. Further note that this method internally uses this
analyzer's working set. Finally, note that, after processing a
production, this method sets the production's Properties.RESTRICT property.e - The element.true if the element restricts the input.public boolean consumesInput(Element e)
process() invocations must have been
performed. Further note that this method internally uses this
analyzer's working set. Finally, note that, after processing a
production, this method sets the production's Properties.CONSUMER property.e - The element.true if the element consumes the input.public boolean matchesEmpty(Element e)
process() invocations must have been
performed. Further note that this method internally uses this
analyzer's working set. Finally, note that, after processing a
production, this method sets the production's Properties.EMPTY property.e - The element.true if the element matches the empty input.public boolean isNotFollowedBy(Element e)
process() invocations must
have been performed.e - The element.true if the specified element is a
not-followed-by predicate.public boolean isBindable(Element e)
true if the specified element is
recognized by bind(List) and bind(List,String)
as capturing a list's semantic value.e - The element.true if the element can be bound.public Binding bind(java.util.List<Element> l)
null to indicate the need for an explicitly
specified semantic value.l - The list to bind.public Binding bind(java.util.List<Element> l, java.lang.String marker)
null to indicate the need for an explicitly
specified semantic value.l - The list to bind.marker - The marker for the binding variable or
null if no marker should be used.public static Binding getBinding(java.util.List<Element> l)
null.l - The list.public static Element unbind(Element e)
e - The element.public static Element stripAndUnbind(Element e)
e is semantically equivalent to:Analyzer.strip(Analyzer.unbind(Analyzer.strip(e)))
e - The element.public Element getValue(java.util.List<Element> list, boolean ignoreActions)
null.list - The list.ignoreActions - The flag for whether to ignore (parser)
actions.null if the value cannot
be determined.public static boolean setsValue(java.util.List<Element> l, boolean all)
yyValue, an action setting
yyValue, or a value element.l - The list.all - The flag for whether all alternatives of nested
choices need to set the semantic value.true if the list sets the semantic value.public static boolean setsValue(Element e, boolean all)
yyValue, an action
setting yyValue, or a value element.e - The element.all - The flag for whether all alternatives of choices need
to set the semantic value.true if the element sets the semantic value.public static boolean setsNullValue(java.util.List<Element> l)
null. This method determines
whether the only value-setting element is a null value. It
ignores nested choices and sequences.l - The list.true if the list sets the semantic value to
null.public boolean mayBeNull(Element element)
null. This method returns true if the
specified element is an option or a nonterminal representing a
desguared option.element - The element.true if the element's value may be
null.public Type type(Element element)
AST and may return a Wildcard.element - The element.java.lang.IllegalArgumentException - Signals that the element cannot
be typed.Copyright © 2014. All Rights Reserved.