com.adobe.xfa.formcalc.SymbolTable Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2007 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.formcalc;
import java.util.List;
/**
* Class SymbolTable defines the symbol table used by the
* FormCalc scripting engine.
* The FormCalc parser in fact, maintains two symbols tables: one
* for all built-in functions and a separate one for variables,
* parameters and functions.
*
* The symbol table for built-ins is quite static in size, but its
* contents can span several invocations of yyparse(). Conversely, the
* symbol table for variables, parameters and functions needs to grow
* to as many variables, parameters and functions as are defined in the
* FormCalc script, and needs to contract its contents before each
* invocation of yyparse().
*
* @author Paul Imerson, Mike P. Tardif
*
* @exclude from published api.
*/
public final class SymbolTable {
static final int SIZE = 509; // size must be prime!
/**
* Instantiates a SymbolTable object.
*/
SymbolTable() {
// empty
}
/**
* Creates storage for this object.
*
* @param nTableSize a size for this object' s hash table.
* This defines the number of buckets in the hash table. For optimal
* results this number should be prime, and sufficiently large to avoid
* collisions.
* @return integer 1 upon success, and 0 otherwise.
*/
int create(int nTableSize /* = SIZE */) {
mnTableSize = nTableSize;
moTableBase = new CalcSymbol[nTableSize];
return 1;
}
/**
* Gets this object's current table size.
*
* @return the current table size.
*/
int getTableSize() {
return mnTableSize;
}
/**
* (Re-)Initializes this object. Depending upon type
* and other attributes, unneeded symbols in the table are deleted.
*
* @param bSaveMode the save state.
*/
void init(CalcParser oParser) {
for (int i = 0; i < mnTableSize; i++) {
CalcSymbol prev = null;
CalcSymbol next = null;
for (CalcSymbol p = moTableBase[i]; p != null; p = next) {
next = p.getNext();
int store = p.getStore();
if ((store & CalcSymbol.StorePrelim)
== CalcSymbol.StorePrelim) {
if (! oParser.mbSyntaxErrorSeen) {
store &= ~CalcSymbol.StorePrelim;
p.setStore(store);
}
else {
if (p == moTableBase[i])
prev = moTableBase[i] = next;
else
prev.setNext(next);
continue;
}
}
int type = p.getType();
if (p.getStore() == CalcSymbol.StoreFroz
|| type == CalcSymbol.TypeFunction) {
if (! oParser.mbWasInSaveMode) {
if (p == moTableBase[i])
prev = moTableBase[i] = next;
else
prev.setNext(next);
continue;
}
}
else if (type == CalcSymbol.TypeVariable
|| type == CalcSymbol.TypeReference) {
if (p.getScope() > 1) {
if (p == moTableBase[i])
prev = moTableBase[i] = next;
else
prev.setNext(next);
continue;
}
else if (! oParser.mbWasInSaveMode) {
if (p == moTableBase[i])
prev = moTableBase[i] = next;
else
prev.setNext(next);
continue;
}
}
prev = p;
}
}
}
/**
* Looks for the given symbol in this object. If found, the
* symbol is returned. The search is confined to Function, Parameter
* and Builtin-type symbols.
*
* @param sName the name of the symbol being searched for.
* @return the located symbol or null if not found.
*/
CalcSymbol lookup(String sName) {
assert(sName != null);
CalcSymbol q = null;
int h = hash(sName);
for (CalcSymbol p = moTableBase[h]; p != null; p = p.getNext()) {
if (sName.equals(p.getName())) {
int type = p.getType();
if (type == CalcSymbol.TypeFunction)
return p;
else if (type == CalcSymbol.TypeBuiltin)
return p;
else if (type == CalcSymbol.TypeParameter)
return p;
}
}
return q;
}
/**
* Looks up the given symbol in this object. If found, the
* symbol is returned. Variable-type symbols returned will have the
* largest scope of all currently active scopes.
*
* @param sName the name of the symbol being searched for.
* @param oScope the scope of the symbol being searched for.
* @return the located symbol or null if not found.
*/
CalcSymbol lookup(String sName, ScopeTable oScope) {
assert(sName != null);
CalcSymbol q = null;
int h = hash(sName);
for (CalcSymbol p = moTableBase[h]; p != null; p = p.getNext()) {
if (sName.equals(p.getName())) {
int type = p.getType();
if ((type == CalcSymbol.TypeVariable
|| type == CalcSymbol.TypeReference)
&& oScope.isActive(p.getScope())) {
if (q == null)
q = p;
else if (p.getScope() > q.getScope())
q = p;
}
else if (p.getType() == CalcSymbol.TypeParameter)
q = p;
}
}
return q;
}
/**
* Looks up an existing the symbol in this object.
* The symbol must have the same name, be a variable, and must
* have the same scope as the given. Effectively this is
* searching for an alias.
*
* @param oSym the symbol alias being searched for.
* @return the located symbol or null if not found.
*/
CalcSymbol lookup(CalcSymbol oSym) {
assert(oSym != null);
CalcSymbol q = null;
int h = hash(oSym.getName());
for (CalcSymbol p = moTableBase[h]; p != null; p = p.getNext()) {
String sName = p.getName();
if (sName != null && sName.equals(oSym.getName())) {
int type = p.getType();
if ((type == CalcSymbol.TypeVariable
|| type == CalcSymbol.TypeReference)
&& p.getScope() == oSym.getScope())
q = p;
}
}
return q;
}
/**
* Installs the given symbol. A new symbol is created, and added to the
* SymbolTable object.
*
* @param sName the name of the symbol being inserted.
* @return the inserted symbol.
*/
CalcSymbol install(String sName) {
assert(sName != null);
int h = hash(sName);
CalcSymbol p = new CalcSymbol();
p.setName(sName);
p.setNext(moTableBase[h]);
moTableBase[h] = p;
return p;
}
/**
* Enumerates entries in this object. It populates
* a list of CalcSymbol pointers to variables, references
* and parameters. Symbols are not copied, so they must not
* be stored for later use.
*
* @param oScope the scope of the symbol being searched for.
* @param oSymbols the returned list of symbols.
*/
public void enumerate(ScopeTable oScope, List oSymbols) {
for (int h = 0; h < mnTableSize; h++) {
for (CalcSymbol p = moTableBase[h]; p != null; p = p.getNext()) {
boolean bAdd = false;
int type = p.getType();
if ((type == CalcSymbol.TypeVariable
|| type == CalcSymbol.TypeReference)
&& oScope.isActive(p.getScope())) {
bAdd = true;
}
else if (p.getType() == CalcSymbol.TypeParameter)
bAdd = true;
if (bAdd)
oSymbols.add(p);
}
}
}
/**
* Hashes a name.
*
* @param sName the name being hashed.
* @return the hash value.
*/
private int hash(String sName) {
assert(sName != null);
int h = 0;
for (int i = 0, n = sName.length(); i < n; i++)
h = h << 1 ^ sName.charAt(i);
h %= mnTableSize;
if (h < 0)
h = -h;
return h;
}
private CalcSymbol[] moTableBase; // a dynamic array of CalcSymbols
private int mnTableSize; // the table size
}