com.adobe.xfa.formcalc.CalcParser.jj Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/**
* The class CalcParser defines the FormCalc parser. It uses
* JavaCC to generate
* the necessary Java classes from this source.
* Running JavaCC on this source will generate the sources
* for the following Java classes:
*
* - TokenMgrError
*
- Token
*
- ParseException
*
- JavaCharStream
*
- CalcParserTokenManager
*
- CalcParserConstants
*
- CalcParser
*
* Do not edit any of these generated Java classes.
*
* The C++ implementation used a LALR yacc-based parser. JavaCC
* generates LL (recursive descent) parsers. This means than
* left-recursive production are verboten. Thus all left-recursive
* productions in the Yacc-based grammar of the form:
*
* A ::= B | A C
*
* are now specified as
*
* A ::= B ( C )*
*
* herein.
*
* Lastly, it was not evident how to integrate our own
* lexical analyzer, so we've use JavaCC's.
*/
options {
JDK_VERSION = "1.5";
STATIC = false;
UNICODE_INPUT = true;
/*
* The any of following may be enable to debug parser issues.
*/
DEBUG_TOKEN_MANAGER = false;
DEBUG_PARSER = false;
DEBUG_LOOKAHEAD = false;
}
PARSER_BEGIN(CalcParser)
/*
* Do not edit this JavaCC-generated Java class.
*
* 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.lang.reflect.Method;
import java.io.StringReader;
import java.util.EnumSet;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.LcLocale;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringUtils;
/**
* This class defines the FormCalc scripting engine. It embodies
* both the parser and interpreter for the FormCalc language.
*
*
* Here's a simple example demonstrating the use of this class.
* The colored sequence of instructions can be repeated ad infinitum.
*
* import com.adobe.xfa.formcalc.CalcParser;
* ...
* CalcParser oParser = new CalcParser();
* //
* // Specify a script host. This is mandatory.
* //
* oParser.setScriptHost(...);
* //
* // Specify a display host. This is optional.
* //
* oParser.setDisplayHost(...);
* //
* // Specify a calculation.
* //
* oParser.putScript(L"if (4 * atan(1) eq pi(), \"Eureka!\")");
* //
* // Parse and evaluate calculation.
* //
* oParser.evaluate(false, false);
* //
* // Retrieve and classify the result.
* //
* CalcSymbol Symbol = oParser.getCalcSymbol();
* String sResult;
* switch(Symbol.getType()) {
* case CalcSymbol.TypeString:
* sResult = Symbol.getStringValue();
* break;
* case CalcSymbol.TypeReturn:
* sResult = Symbol.getStringValue();
* break;
* case CalcSymbol.TypeError:
* sResult = Symbol.getErrorValue(null, null);
* break;
* case CalcSymbol.TypeNull:
* sResult = "null";
* break;
* }
* System.out.println(sResult);
*
*
* @author Paul Imerson, Mike P. Tardif
*
* @exclude from published api.
*/
@FindBugsSuppress(code="Nm,Bx,UrF")
@SuppressWarnings("unchecked")
public class CalcParser implements Cloneable {
/**
* Enumerate scripting legacy versions.
*
* This enumeration defines a mapping between vX.Y-scripting legacy flags
* to a set of internal legacy scripting behaviours.
* These enumerations are defined as a set; hence the i'th enumeration
* must have value 2^i - 1.
* JAVA PORT: Define LegacyVersion as Java enum
*/
public enum LegacyVersion
{
/*
* Use values 0, 1 and 3 just like in XFA code. Although, strictly speaking, it isn't necessary to define
* it in such a manner, but this helps keep the code in both the cases as close as possible.
*/
CUR_SCRIPTING(0), /* no legacy scripting behaviour */
V30_SCRIPTING(1), /* v3.0 legacy scripting behaviour */
V32_SCRIPTING(2); /* v3.2 legacy scripting behaviour */
private LegacyVersion(int nValue){
value=nValue;
}
private final int value;
final int getValue(){
return value;
}
}
public static final int CODESIZE = 512; // must be a power of 2!
public static final int DATASIZE = 509; // must be a prime!
/**
* Instantiates a CalcParser object.
*/
public CalcParser() {
this(CODESIZE, DATASIZE);
}
/**
* Instantiates a CalcParser object.
*
* @param nCodeSize an initial size for instruction memory.
* @param nDataSize an initial size for data memory.
*/
CalcParser(int nCodeSize /* = CODESIZE */, int nDataSize /* = DATASIZE */) {
this(System.in);
create(nCodeSize, nDataSize);
}
/**
* Clones this object.
*
* Clone a new CalcParser object from the properties of this object.
*
* @return the new CalcParser.
*/
public Object clone() {
CalcParser oParser = null;
try {
oParser = (CalcParser) super.clone();
oParser.create(moCode.getCodeSize(), moData.getTableSize());
oParser.setDisplayHost(moDisplayHost);
oParser.setScriptHost(moScriptHost);
oParser.setProtocolHost(moProtocolHost);
oParser.setDebugHost(moDebugHost);
oParser.setLocale(msLocaleName);
oParser.setDupsMode(mbAllowDups);
oParser.setLegacyScripting(moLegacyScripting);
} catch(CloneNotSupportedException e) {
;
}
return oParser;
}
/*
* Create required parser and interpreter components.
*
* @param nCodeSize initial size of instruction memory.
* @param nDataSize initial size of data memory.
*/
boolean create(int nCodeSize, int nDataSize) {
moCode = new Instruction();
if (moCode.create(nCodeSize) == 0)
return false;
moData = new SymbolTable();
if (moData.create(nDataSize) == 0)
return false;
moScope = new ScopeTable();
if (moScope.create(ScopeTable.SIZE) == 0)
return false;
moFrame = new FrameTable();
if (moFrame.create(FrameTable.SIZE) == 0)
return false;
mStack = new Stack();
if (mStack.create(Stack.SIZE) == 0)
return false;
mBuiltin = new SymbolTable();
if (mBuiltin.create(97) == 0)
return false;
Builtins.init(mBuiltin);
moDisplayHost = null;
moScriptHost = null;
moProtocolHost = null;
moDebugHost = null;
mnScriptID = -1;
LcLocale oLocale = new LcLocale(LcLocale.getLocale());
if (! oLocale.isValid())
oLocale = new LcLocale(LcLocale.DEFAULT_LOCALE);
msLocaleName = oLocale.getIsoName();
mbWasInSaveMode = false;
mbInSaveMode = false;
mbInSyntaxCheckMode = false;
mbInUse = false;
mbAllowDups = true;
mbSyntaxErrorSeen = false;
mbDebugEnabled = false;
mbInterrupted = false;
moLegacyScripting = EnumSet.of(LegacyVersion.CUR_SCRIPTING);
mnSavedDecl = 0;
moResult = null;
return true;
}
/*
* Handle a syntax error: generate error symbols and push it
* on the runtime stack.
*
* @param nResId the resource id used to format the error message.
* @param token the error message token parameter.
*/
void yyError(int nResId) {
if (! mbSyntaxErrorSeen)
yyError(nResId, token.image);
}
/*
* Handle a syntax error: generate error symbols and push it
* on the runtime stack.
*
* @param nResId the resource id used to format the error message.
* @param token the error message token parameter.
*/
void yyError(int nResId, String sToken) {
if (! mbSyntaxErrorSeen) {
mbInThrow = true;
Token t = token;
if (t.next != null && t.next.image.length() > 0)
t = t.next;
MsgFormatPos oErr = new MsgFormatPos(nResId);
oErr.format(sToken); // token
String sLineNo = Integer.toString(t.beginLine);
oErr.format(sLineNo); // line number
String sColNo = Integer.toString(t.beginColumn);
oErr.format(sColNo); // column number
CalcSymbol oSym = new CalcSymbol(oErr.toString(), true, t.beginLine, nResId);
mStack.push(oSym);
mbSyntaxErrorSeen = true;
throw new RuntimeException();
}
}
/*
* Parse the current source and generate code.
* @return boolean false when errors were detected during
* compilation, and true otherwise.
*/
boolean yyParse() {
if (mbInUse) {
mbInThrow = true;
MsgFormatPos sErr = new MsgFormatPos(ResId.FC_SYS_ERR_REENT);
CalcSymbol oSym = new CalcSymbol(sErr.toString(), true, 0, 0);
mStack.push(oSym);
setCalcResult(oSym);
return false;
}
mbInUse = true;
//
// Re-initialize the parser and interpreter on entry.
//
moCode.init(this);
moData.init(this);
moScope.init(this);
mStack.init();
moFrame.init();
mbWasInSaveMode = mbInSaveMode;
mbInDowntoLoop = false;
mbInVarDeclaration = false;
mbInFuncDeclaration = false;
mbInFuncParameters = false;
mbInLoopDeclaration = false;
mbInForeachLoop = false;
mbInThrow = false;
mbInBreak = false;
mbInContinue = false;
// mbInAccessor = false; Javaport: not used.
mbDeleteOk = false;
mbSyntaxErrorSeen = false;
// mbNoTokenssSeen = true; Javaport: not used.
mbCancelStatus = false;
mnLoopOffset = 0;
// mnLastLineSeen = 0; Javaport: not used.
//
// Parse the script, and generate pseudo code.
//
try {
FormCalculation();
} catch (RuntimeException e) {
if (! mbSyntaxErrorSeen) {
CalcSymbol oSym = new CalcSymbol(e.toString(), true, 0, 0);
mStack.push(oSym);
}
} catch (ParseException e) {
Token t = e.currentToken;
if (t.next != null && t.next.image.length() > 0)
t = t.next;
MsgFormatPos oErr = new MsgFormatPos(ResId.FC_ERR_SYNTAX);
oErr.format(t.image);
String sLineNo = Integer.toString(t.beginLine);
oErr.format(sLineNo);
String sColNo = Integer.toString(t.beginColumn);
oErr.format(sColNo);
CalcSymbol oSym = new CalcSymbol(oErr.toString(), true, t.beginLine, 0);
mStack.push(oSym);
mbSyntaxErrorSeen = true;
} catch (TokenMgrError e) {
CalcSymbol oSym = new CalcSymbol(e.toString(), true, 0, 0);
mStack.push(oSym);
mbSyntaxErrorSeen = true;
}
//
// Add an extra instruction in case of syntax errors.
//
generate(Instruction.gStop);
//
// Note: there will always be one symbol on top of the stack,
// when there are syntax/semantic errors!
//
if (mbSyntaxErrorSeen) {
setCalcResult(mStack.pop());
cleanCode();
}
else {
moResult = null;
}
mbInUse = false;
return (! mbSyntaxErrorSeen);
}
void yyTrace(String s) {
// Javaport: not needed. For tracing, set JavaCC option DEBUG_PARSER instead.
}
/*
* Interpret the current source. yyParse() must
* already have been called successfully.
*
*/
void execute() {
if (mbInUse) {
mbInThrow = true;
MsgFormatPos sErr = new MsgFormatPos(ResId.FC_SYS_ERR_REENT);
CalcSymbol oSym = new CalcSymbol(sErr.toString(), true, 0, 0);
mStack.push(oSym);
setCalcResult(oSym);
}
//
// If successfully parsed Then interpret the pseudo code, pop off
// the resulting symbol and save its value.
//
if (mbSyntaxErrorSeen)
return;
mbInUse = true;
moCode.execute(this, moCode.getCodeStart());
setCalcResult(mStack.pop());
cleanCode();
mbInUse = false;
}
/*
* Release or relocate code according to the setting
* of mbInSaveMode.
*/
void cleanCode() {
//
// Release all resources consumed from code generation and
// interpretation. Relocate code if save mode is turned on.
//
mbDeleteOk = true;
if (mbSyntaxErrorSeen)
moCode.release(this, moCode.getProgStart());
else if (mbInSaveMode)
moCode.relocate(this);
else
moCode.release(this, moCode.getCodeStart());
}
/*
* Set the intermediate code saviour mode for all subsequent compilations.
*
* @param bSaveMode saves the intermediate code of global variable
* and function definitions when set, and discarts the intermediate code
* of subsequent compilations when reset.
*/
void setSaveMode(boolean bSaveMode) {
mbInSaveMode = bSaveMode;
}
/**
* Set (specify) a {@link DisplayHost}.
*
* This method identifies a host capable of displaying message box
* dialogs. Without such a host, all MessageBox calcs will fail.
*
*
Use of this method is optional,
* but should be invoked before any FormCalc script is evaluated.
*
* @param oDisplayHost an interface to the display host.
*/
public void setDisplayHost(DisplayHost oDisplayHost) {
moDisplayHost = oDisplayHost;
if (moDisplayHost != null)
Builtins.add(mBuiltin, "MessageBox", com.adobe.xfa.formcalc.BuiltinMisc.class);
}
/**
* Set (specify) a {@link ScriptHost}.
*
* This method identifies a host capable of resolving SOM references.
*
*
Use of this method is mandatory
* and should be invoked before any FormCalc script is evaluated.
*
* @param oScriptHost an interface to the script host.
*/
public void setScriptHost(ScriptHost oScriptHost) {
moScriptHost = oScriptHost;
}
/**
* Set (specify) a scripting legacy flag.
*
* This method sets the state of a scripting legacy flag.
*
* @param oLegacyScripting the state of the scripting legacy flag.
*/
public void setLegacyScripting(EnumSet oLegacyScripting) {
moLegacyScripting = EnumSet.copyOf(oLegacyScripting);
}
/**
* Set (specify) a {@link ProtocolHost}.
*
* This method identifies a host capable of getting/putting/posting URLs.
*
*
Use of this method is optional
* but should be invoked before any FormCalc script is evaluated.
*
* @param oProtocolHost an interface to the protocol host.
*/
public void setProtocolHost(ProtocolHost oProtocolHost) {
moProtocolHost = oProtocolHost;
if (moProtocolHost != null) {
Builtins.add(mBuiltin, "Get", com.adobe.xfa.formcalc.BuiltinUrl.class);
Builtins.add(mBuiltin, "Put", com.adobe.xfa.formcalc.BuiltinUrl.class);
Builtins.add(mBuiltin, "Post", com.adobe.xfa.formcalc.BuiltinUrl.class);
}
}
/**
* Set (specify) a {@link DebugHost}.
*
* This method identifies a host capable of acting as a debugger.
*
*
Use of this method is optional
* but should be invoked before any FormCalc script is evaluated.
*
* @param oDebugHost an interface to the debug host.
*/
public void setDebugHost(DebugHost oDebugHost) {
moDebugHost = oDebugHost;
}
/**
* Provide an identifier for the script that will be compiled
* or evaluated next.
*
* Set the script ID. Script IDs are used to identify which script
* is invoking a break-point callback via {@link DebugHost}.
* It's not necessarily the most
* recently-invoked script, since function definitions can be cached.
* @param nScriptID the script ID.
*/
public void setScriptID(int nScriptID) {
mnScriptID = nScriptID;
}
/*
* Enable debugging support. This will cause line numbers
* to be stored internally.
*/
public void debugEnable(boolean bEnableDebug) {
mbDebugEnabled = bEnableDebug;
}
/*
* Get one (the first) symbol referenced by the given accessor symbol.
*
* @param oSymIn CalcSymbol.
*/
CalcSymbol getOneValue(CalcSymbol oSymIn) {
CalcSymbol oSym = new CalcSymbol(oSymIn);
do {
switch (oSym.getType()) {
case CalcSymbol.TypeAccessor:
try {
CalcSymbol[] oSyms = moScriptHost.getItemValue(oSym.getName(), oSym.getObjValues());
oSym = oSyms[0];
} catch (CalcException e) {
oSym = e.getSymbol();
}
continue;
case CalcSymbol.TypeReference:
case CalcSymbol.TypeDouble:
case CalcSymbol.TypeString:
case CalcSymbol.TypeNull:
case CalcSymbol.TypeVariable:
case CalcSymbol.TypeError:
case CalcSymbol.TypeReturn:
case CalcSymbol.TypeFunction:
break;
default:
assert(false);
break;
}
break;
} while (true);
CalcSymbol oRetSym = new CalcSymbol(oSym);
return oRetSym;
}
/*
* Get the value symbol referenced by the given reference symbol.
*
* @param oSymIn CalcSymbol.
*/
CalcSymbol getRefValue(CalcSymbol oSymIn) {
CalcSymbol oSym = new CalcSymbol(oSymIn);
switch (oSym.getType()) {
case CalcSymbol.TypeReference:
try {
if (oSym.getObjValue() != null) {
CalcSymbol[] oSyms = moScriptHost.getItemValue("#0", oSym.getObjValues());
oSym = oSyms[0];
}
else if (oSym.getName() != null && oSym.getName().length() > 0) {
mbInThrow = true;
MsgFormatPos sFmt = new MsgFormatPos(ResId.FC_ERR_REF_NULL);
sFmt.format(oSym.getName());
oSym = new CalcSymbol(sFmt.toString(), true, 0, 0);
}
else {
oSym = new CalcSymbol();
}
} catch (CalcException e) {
oSym = e.getSymbol();
}
break;
default:
assert(false);
break;
}
CalcSymbol oRetSym = new CalcSymbol(oSym);
return oRetSym;
}
/*
* Get the numeric value of the given symbol.
*
* @param oSymIn CalcSymbol.
*/
double getNumeric(CalcSymbol oSymIn) {
double nRetVal = Double.MAX_VALUE; // sentinel value;
do {
CalcSymbol oSym = null;
switch (oSymIn.getType()) {
case CalcSymbol.TypeAccessor:
oSym = getOneValue(oSymIn);
if (oSym.getType() != CalcSymbol.TypeError
&& oSymIn.getName().indexOf('*') >= 0) { // more orecisely, "[*]"
mbInThrow = true;
throw new CalcException();
}
oSymIn = oSym;
continue;
case CalcSymbol.TypeReference:
oSym = getRefValue(oSymIn);
oSymIn = oSym;
continue;
case CalcSymbol.TypeDouble:
nRetVal = oSymIn.getNumericValue();
break;
case CalcSymbol.TypeString:
nRetVal = FormCalcUtil.strToDbl(oSymIn.getStringValue(), false);
break;
case CalcSymbol.TypeVariable:
String sVal = oSymIn.getStringValue();
if (sVal != null)
nRetVal = FormCalcUtil.strToDbl(sVal, false);
else
nRetVal = 0.;
break;
case CalcSymbol.TypeFunction:
case CalcSymbol.TypeNull:
nRetVal =0.;
break;
case CalcSymbol.TypeError:
case CalcSymbol.TypeReturn:
mbInThrow = true;
throw new CalcException(oSymIn);
default:
assert(false);
break;
}
break;
} while (true);
return nRetVal;
}
/*
* Get the actual type of the given symbol; that is, if oSymIn points to
* an accessor or a reference, return the type of the ref value rather than
* oSymIn.getType().
*
* @param oSymIn CalcSymbol.
*/
CalcSymbol getActualType(CalcSymbol oSymIn) {
CalcSymbol cRetVal = null; // sentinel value;
do {
CalcSymbol oSym = null;
cRetVal = new CalcSymbol(oSymIn);
switch (oSymIn.getType()) {
case CalcSymbol.TypeAccessor:
oSym = getOneValue(oSymIn);
oSymIn = oSym;
continue;
case CalcSymbol.TypeReference:
oSym = getRefValue(oSymIn);
oSymIn = oSym;
continue;
case CalcSymbol.TypeVariable:
String sVal = oSymIn.getStringValue();
if (null == sVal)
{
//Enforces TypeNull
cRetVal = new CalcSymbol();
}
break;
default:
break;
}
break;
} while (true);
return cRetVal;
}
/*
* Get the Cancel Status for the script.
*
*/
boolean getCancelStatus(){
return mbCancelStatus;
}
/*
* Set the Cancel Status for the script.
*
* @param bStatus boolean.
*/
void setCancelStatus(boolean bStatus) {
mbCancelStatus = bStatus;
}
/*
* Get the string value of the given symbol.
*
* @param oSymIn CalcSymbol.
*/
String getString(CalcSymbol oSymIn) {
String sRetVal = "E Pluribus Unix"; // sentinel value;
do {
CalcSymbol oSym = null;
switch (oSymIn.getType()) {
case CalcSymbol.TypeAccessor:
oSym = getOneValue(oSymIn);
if (oSym.getType() != CalcSymbol.TypeError
&& oSymIn.getName().indexOf('*') >= 0) { // more orecisely, "[*]"
mbInThrow = true;
throw new CalcException();
}
oSymIn = oSym;
continue;
case CalcSymbol.TypeReference:
oSym = getRefValue(oSymIn);
oSymIn = oSym;
continue;
case CalcSymbol.TypeDouble:
oSymIn.setTypeToString();
sRetVal = oSymIn.getStringValue();
break;
case CalcSymbol.TypeString:
sRetVal = oSymIn.getStringValue();
break;
case CalcSymbol.TypeVariable:
sRetVal = oSymIn.getStringValue();
if (sRetVal == null)
sRetVal = "";
break;
case CalcSymbol.TypeFunction:
case CalcSymbol.TypeNull:
sRetVal = "";
break;
case CalcSymbol.TypeError:
case CalcSymbol.TypeReturn:
mbInThrow = true;
throw new CalcException(oSymIn);
default:
assert(false);
break;
}
break;
} while (true);
return sRetVal;
}
/*
* Get the exception value of the given symbol.
*
* @param oSymIn CalcSymbol.
*/
void getExceptions(CalcSymbol oSymIn) {
do {
CalcSymbol oSym = null;
switch (oSymIn.getType()) {
case CalcSymbol.TypeAccessor:
if (mbInBreak || mbInContinue)
break;
oSym = getOneValue(oSymIn);
if (oSym.getType() != CalcSymbol.TypeError
&& oSymIn.getName().indexOf('*') >= 0) { // more precisely, "[*]"
mbInThrow = true;
throw new CalcException();
}
oSymIn = oSym;
continue;
case CalcSymbol.TypeReference:
case CalcSymbol.TypeDouble:
case CalcSymbol.TypeString:
case CalcSymbol.TypeVariable:
case CalcSymbol.TypeFunction:
case CalcSymbol.TypeNull:
break;
case CalcSymbol.TypeError:
case CalcSymbol.TypeReturn:
mbInThrow = true;
throw new CalcException(oSymIn);
default:
assert(true);
break;
}
break;
} while (true);
}
/*
* Set the (calculation) result to the given value.
*
* @param oSymIn CalcSymbol.
*/
void setCalcResult(CalcSymbol oSymIn) {
try {
do {
CalcSymbol oSym = null;
switch (oSymIn.getType()) {
case CalcSymbol.TypeAccessor:
oSym = getOneValue(oSymIn);
oSymIn.assign(oSym);
continue;
case CalcSymbol.TypeReference:
oSym = getRefValue(oSymIn);
oSymIn.assign(oSym);
break;
case CalcSymbol.TypeDouble:
oSymIn.setTypeToString();
break;
case CalcSymbol.TypeReturn:
case CalcSymbol.TypeVariable:
case CalcSymbol.TypeString:
case CalcSymbol.TypeNull:
case CalcSymbol.TypeError:
break;
default:
assert(false);
break;
}
break;
} while (true);
moResult = new CalcSymbol(oSymIn);
} catch (CalcException e) {
moResult = e.getSymbol();
}
if (moResult.getType() == CalcSymbol.TypeVariable) {
moResult.setType(moResult.getStringValue() != null ? CalcSymbol.TypeString : CalcSymbol.TypeNull);
}
//
// Watson bug 1357801 don't strip off the sign char.
//
/*
if (moResult.getType() == CalcSymbol.TypeString) {
String sStr = moResult.getStringValue();
if (FormCalcUtil.strIsNumeric(sStr)) {
StringBuilder sBuf = new StringBuilder(sStr);
FormCalcUtil.trimZeroes(sBuf);
FormCalcUtil.trimRadix(sBuf);
FormCalcUtil.trimSign(sSBuf);
moResult.setStrValue(sBuf.toString());
}
}
*/
}
/**
* Determine if the symbol given already exists at the scope given.
*
* @param pName the name of the symbol being checked.
* @return the symbol if the given identifier is a variable
* at the scope given, and NULL otherwise.
*/
private CalcSymbol varExists(String sName, ScopeTable oScope) {
CalcSymbol oSym = moData.lookup(sName, oScope);
if (oSym != null) {
if (oSym.getType() == CalcSymbol.TypeVariable)
return (oSym.getScope() == oScope.getScope()) ? oSym : null;
else if (oSym.getType() == CalcSymbol.TypeParameter)
return oSym;
}
return null;
}
private int generate(Object oInstruction) {
if (mbDebugEnabled) {
if (oInstruction instanceof Method) {
Method oMethod = (Method) oInstruction;
if (oMethod == Instruction.gEnter || oMethod == Instruction.gExit)
setLine();
}
throw new ExFull(ResId.UNSUPPORTED_OPERATION, "CalcParser#generate");
// return moCode.generate(oInstruction, mnScriptID, mnLastLineSeen);
}
else
return moCode.generate(oInstruction);
}
private void setLine() {
Token t = token;
if (t.next != null)
t = t.next;
// mnLastLineSeen = t.beginLine; // Javaport: not used.
}
/**
* Specify the FormCalc script that will be compiled or evaluated next.
*
* @param sCalc the FormCalc script.
*/
public void putScript(String sCalc) {
ReInit(new StringReader(sCalc));
}
/**
* Specify the operating locale. If omitted, it will default to the
* ambient locale.
*
* @param sLocale the (RFC-1766) locale name.
*/
public void setLocale(String sLocale) {
if (!StringUtils.isEmpty(sLocale))
msLocaleName = sLocale;
}
/**
* Get the strictness mode for the redefinition of global variables
* and function.
*
* @return boolean - the strictness mode.
*/
public boolean getDupsMode() {
return mbAllowDups;
}
/**
* Set the strictness mode for the redefinition of global variables
* and function.
*
* @param bAllowDups allow the redefinition of global variables
* and functions when set.
*/
public void setDupsMode(boolean bAllowDups) {
mbAllowDups = bAllowDups;
}
/**
* Set the parser into syntax-check mode. This means that
* functions are assumed to exist; unknown functions do not
* cause a syntax error during parsing.
*
* @param bSyntaxCheckMode Specify the syntax-check mode.
*/
public void setSyntaxCheckMode(boolean bSyntaxCheckMode) {
mbInSyntaxCheckMode = bSyntaxCheckMode;
}
/**
* Compile (only) the FormCalc script.
*
*
Upon syntax errors, text describing error is available by
* invoking the {@link #getCalcResult()} method.
*
*
When saving the resulting intermediate code (bSaveDeclarations), only
* the code from function declarations and global variable declarations
* is saved, unless bSaveAllCode is true.
*
*
This method is provided for specialized debugging environments,
* as it is more efficient to simly invoke the
* {@link #evaluate(boolean, boolean)} method.
*
* @param bSaveDeclarations save the resulting intermediate code relating
* to function declarations and global variable declarations upon success
* when set, and don't save it when reset.
* @param bSaveAllCode save all generated code upon success when set,
* and don't save it when reset. The saved code can be executed by calling
* Evaluate with the bExecSavedCode arameter set.
* @param bSyntaxCheckOnly if the saved code will not be executed, then
* set this flag to true. This will mean that missing functions are not
* considered errors (since they are assumed to exist elsewhere).
* @return boolean false on syntax errors, and true otherwise.
*/
public boolean compile(boolean bSaveDeclarations /* = false */,
boolean bSaveAllCode /* = false */,
boolean bSyntaxCheckOnly /* = false */) {
setSaveMode(bSaveDeclarations);
setSyntaxCheckMode(bSyntaxCheckOnly);
if (! yyParse())
return false;
if (! bSaveAllCode)
cleanCode();
return true;
}
/**
* (Compile and) Evaluate the FormCalc script.
*
*
This method always yield a result, which is an object of type
* {@link CalcSymbol}. That object is
* is available by invoking the {@link #getCalcResult()}
* method.
*
*
When saving the resulting intermediate code (bSaveDeclarations),
* only
* code from function declarations and global variable declarations
* is saved.
*
* @param bSaveDeclarations save the resulting intermediate code relating
* to function declarations and global variable declarations upon success
* when set, and don't save it when reset.
* @param bExecSavedCode execute saved code upon success when set,
* and regenerate code (from original source) when reset.
* @return boolean false on syntax errors, and true otherwise.
*/
public boolean evaluate(boolean bSaveDeclarations /* = false */,
boolean bExecSavedCode /* = false */) {
setSaveMode(bSaveDeclarations);
setSyntaxCheckMode(false);
if (! bExecSavedCode && ! yyParse())
return false;
execute();
return true;
}
/**
* Is this FormCalc object already in use?
*
*
This method determines if the FormCalc is in the middle of
* evaluating a script. The FormCalc parser is YACC based, and
* hence not re-entrant. Re-invoking the parser when in use, throws
* an excetion. Use this method to avert such exceptions.
*
* @return boolean true when in use, and false otherwise.
*/
public boolean inUse() {
return mbInUse;
}
/**
* Retrieve the calculation (or compilation) result.
*
*
If the evaluated (or compiled) Formcalc script:
*
*
* - contained a syntax error,
*
- the resulting CalcSymbol object will be of type
* CalcSymbol.TypeError.
* Use {@link CalcSymbol#getErrorValue(IntegerHolder, IntegerHolder)}
* to access the associated error message text.
*
- evaluated to a runtime error,
*
- the resulting CalcSymbol object will again be of type
* CalcSymbol.TypeError. Again use
* {@link CalcSymbol#getErrorValue(IntegerHolder, IntegerHolder)}
* to access the associated error message text.
*
- evaluated to an excetion resulting from execution
* of a return() exression,
*
- the resulting CalcSymbol object will be of type
* CalcSymbol.TypeReturn. Use
* {@link CalcSymbol#getStringValue()}
* to access the associated string value.
*
- evaluated to a null-valued result,
*
- the resulting CalcSymbol object will again be of type
* CalcSymbol.TypeNull.
*
- evaluated to a string-valued or numeric-valued result,
*
- the resulting CalcSymbol object will again be of type
* CalcSymbol.TypeString. Use
* {@link CalcSymbol#getStringValue()}
* to access the associated string value.
*
*
*
* @return the resulting object. It's the application's responsability to
*/
public CalcSymbol getCalcResult() {
return moResult;
}
public Instruction moCode; // the instruction memory.
public SymbolTable moData; // the data memory.
public ScopeTable moScope; // the scope info.
public FrameTable moFrame; // the frame table.
public Stack mStack; // the runtime stack.
SymbolTable mBuiltin; // the builtin table.
String msLocaleName; // the operating locale name.
ScriptHost moScriptHost; // the script host.
DisplayHost moDisplayHost; // the display host.
ProtocolHost moProtocolHost; // the protocol host.
DebugHost moDebugHost; // the debug host.
int mnLoopOffset; // the enclosing loop offset.
int mnSavedDecl; // the saved declaration count.
int mnScriptID; // an optional ID for this script (for debugging)
// the parser state flags.
boolean mbCancelStatus;
boolean mbWasInSaveMode;
boolean mbInSaveMode;
boolean mbInSyntaxCheckMode;
boolean mbInDowntoLoop;
boolean mbInVarDeclaration;
boolean mbInFuncDeclaration;
boolean mbInFuncParameters;
boolean mbInLoopDeclaration;
boolean mbInForeachLoop;
boolean mbInThrow;
boolean mbInBreak;
boolean mbInContinue;
// boolean mbInAccessor; // Javaport: not used.
boolean mbDeleteOk;
boolean mbSyntaxErrorSeen;
boolean mbInUse;
boolean mbAllowDups;
// boolean mbNoTokensSeen; // Javaport: not used.
boolean mbDebugEnabled;
boolean mbInterrupted;
//Javaport: Implement legacy version as EnumSet. This enables efficient bit twiddling logic in Java
//(albeit via Java's EnumSet pattern/paradigm), while enforcing & maintaining enum based type safety.
EnumSet moLegacyScripting;
private CalcSymbol moResult; // the resulting symbol.
private String msFunc; // the function name.
// private int mnLastLineSeen; // the last line of source encountered. Javaport: not used.
}
PARSER_END(CalcParser)
SKIP : /* WHITESPACE and COMMENT */
{
" "
| "\t"
| "\013"
| "\f"
| "\n"
| "\r"
| < ";" ( ~[ "\n", "\r" ] )* ( "\n" | "\r" | "\r\n" )? >
| < "//" ( ~[ "\n", "\r" ] )* ( "\n" | "\r" | "\r\n" )? >
}
TOKEN : { /* LITERALS */
< INTEGER : >
| < REAL :
"." ( [ "0"-"9" ] )* ( )?
| "." ( )?
| ( )? >
| < #INTEGER_PART : ( [ "0"-"9" ] )+ >
| < #EXPONENT_PART : [ "e", "E" ] ( [ "+", "-" ] )? >
| < #HEXDIGIT : [ "0"-"9", "a"-"f", "A"-"F" ] >
| < STRING :
"\""
( ~[ "\\", "\"", "\n", "\r" ]
| ( "\"\""
| "\\u"
| "\\U"
)
)*
"\"" >
}
TOKEN [IGNORE_CASE] : { /* NULL LITERALS */
< NULL1 : "null" >
| < NULL2 : "%null%" >
}
TOKEN [IGNORE_CASE] : { /* KEYWORDS: keep sorted in increasing string length for best performance. */
< DO : "do" >
| < IF : "if" >
| < IN : "in" >
| < END : "end" >
| < FOR : "for" >
| < VAR : "var" >
| < ELSE : "else" >
| < EXIT : "exit" > /* reserved for future use. */
| < FUNC : "func" >
| < STEP : "step" >
| < THEN : "then" >
| < UPTO : "upto" >
| < BREAK : "break" >
| < ENDIF : "endif" >
| < WHILE : "while" >
| < DOWNTO : "downto" >
| < ELSEIF : "elseif" >
| < ENDFOR : "endfor" >
| < RETURN : "return" > /* reserved for future use. */
| < ENDFUNC : "endfunc" >
| < FOREACH : "foreach" >
| < CONTINUE : "continue" >
| < ENDWHILE : "endwhile" >
}
TOKEN [IGNORE_CASE] : { /* OPERATORS: keep sorted in increasing string length. */
< LT1 : "<" >
| < GT1 : ">" >
| < OR1 : "|" >
| < AND1 : "&" >
| < LE1 : "<=" >
| < NE1 : "<>" >
| < EQ1 : "==" >
| < GE1 : ">=" >
| < EQ2 : "eq" >
| < GE2 : "ge" >
| < GT2 : "gt" >
| < LE2 : "le" >
| < LT2 : "lt" >
| < NE2 : "ne" >
| < OR2 : "or" >
| < AND2 : "and" >
| < NOT : "not" >
}
TOKEN : { /* OPERATORS: keep sorted in increasing string length. */
< PLUS : "+" >
| < MINUS : "-" >
| < STAR : "*" >
| < DIV : "/" >
| < ASGN : "=" >
| < DOT : "." > : ALLOWKEYWORDS
| < DOTDOT : ".." > : ALLOWKEYWORDS
| < DOTHASH : ".#" > : ALLOWKEYWORDS
| < DOTSTAR : ".*" > : ALLOWKEYWORDS
}
TOKEN : { /* PUNCTUATIONS */
< COMMA : "," >
| < LPAREN : "(" >
| < RPAREN : ")" >
| < LBRACE : "[" >
| < RBRACE : "]" >
}
TOKEN : { /* IDENTIFIER */
< IDENT : ( )* >
}
TOKEN : { /* IDENTIFIER or KEYWORD */
< KEYID : ( )* > : DEFAULT
}
TOKEN : {
< ALPHA_PART : [
"!",
"$",
"A"-"Z",
"_",
"a"-"z",
// Javaport: All chars for which Character.isUnicodeIdentifierStart(char) is true.
// Sadly, C++ hasn't kept up with Unicode. Though more recent, this too isn't
// up to the latest Unicode.
"\u00a2"-"\u00a5",
"\u00aa",
"\u00b5",
"\u00ba",
"\u00c0"-"\u00d6",
"\u00d8"-"\u00f6",
"\u00f8"-"\u021f",
"\u0222"-"\u0233",
"\u0250"-"\u02ad",
"\u02b0"-"\u02b8",
"\u02bb"-"\u02c1",
"\u02d0"-"\u02d1",
"\u02e0"-"\u02e4",
"\u02ee",
"\u037a",
"\u0386",
"\u0388"-"\u038a",
"\u038c",
"\u038e"-"\u03a1",
"\u03a3"-"\u03ce",
"\u03d0"-"\u03d7",
"\u03da"-"\u03f3",
"\u0400"-"\u0481",
"\u048c"-"\u04c4",
"\u04c7"-"\u04c8",
"\u04cb"-"\u04cc",
"\u04d0"-"\u04f5",
"\u04f8"-"\u04f9",
"\u0531"-"\u0556",
"\u0559",
"\u0561"-"\u0587",
"\u05d0"-"\u05ea",
"\u05f0"-"\u05f2",
"\u0621"-"\u063a",
"\u0640"-"\u064a",
"\u0671"-"\u06d3",
"\u06d5",
"\u06e5"-"\u06e6",
"\u06fa"-"\u06fc",
"\u0710",
"\u0712"-"\u072c",
"\u0780"-"\u07a5",
"\u0905"-"\u0939",
"\u093d",
"\u0950",
"\u0958"-"\u0961",
"\u0985"-"\u098c",
"\u098f"-"\u0990",
"\u0993"-"\u09a8",
"\u09aa"-"\u09b0",
"\u09b2",
"\u09b6"-"\u09b9",
"\u09dc"-"\u09dd",
"\u09df"-"\u09e1",
"\u09f0"-"\u09f3",
"\u0a05"-"\u0a0a",
"\u0a0f"-"\u0a10",
"\u0a13"-"\u0a28",
"\u0a2a"-"\u0a30",
"\u0a32"-"\u0a33",
"\u0a35"-"\u0a36",
"\u0a38"-"\u0a39",
"\u0a59"-"\u0a5c",
"\u0a5e",
"\u0a72"-"\u0a74",
"\u0a85"-"\u0a8b",
"\u0a8d",
"\u0a8f"-"\u0a91",
"\u0a93"-"\u0aa8",
"\u0aaa"-"\u0ab0",
"\u0ab2"-"\u0ab3",
"\u0ab5"-"\u0ab9",
"\u0abd",
"\u0ad0",
"\u0ae0",
"\u0b05"-"\u0b0c",
"\u0b0f"-"\u0b10",
"\u0b13"-"\u0b28",
"\u0b2a"-"\u0b30",
"\u0b32"-"\u0b33",
"\u0b36"-"\u0b39",
"\u0b3d",
"\u0b5c"-"\u0b5d",
"\u0b5f"-"\u0b61",
"\u0b85"-"\u0b8a",
"\u0b8e"-"\u0b90",
"\u0b92"-"\u0b95",
"\u0b99"-"\u0b9a",
"\u0b9c",
"\u0b9e"-"\u0b9f",
"\u0ba3"-"\u0ba4",
"\u0ba8"-"\u0baa",
"\u0bae"-"\u0bb5",
"\u0bb7"-"\u0bb9",
"\u0c05"-"\u0c0c",
"\u0c0e"-"\u0c10",
"\u0c12"-"\u0c28",
"\u0c2a"-"\u0c33",
"\u0c35"-"\u0c39",
"\u0c60"-"\u0c61",
"\u0c85"-"\u0c8c",
"\u0c8e"-"\u0c90",
"\u0c92"-"\u0ca8",
"\u0caa"-"\u0cb3",
"\u0cb5"-"\u0cb9",
"\u0cde",
"\u0ce0"-"\u0ce1",
"\u0d05"-"\u0d0c",
"\u0d0e"-"\u0d10",
"\u0d12"-"\u0d28",
"\u0d2a"-"\u0d39",
"\u0d60"-"\u0d61",
"\u0d85"-"\u0d96",
"\u0d9a"-"\u0db1",
"\u0db3"-"\u0dbb",
"\u0dbd",
"\u0dc0"-"\u0dc6",
"\u0e01"-"\u0e30",
"\u0e32"-"\u0e33",
"\u0e3f"-"\u0e46",
"\u0e81"-"\u0e82",
"\u0e84",
"\u0e87"-"\u0e88",
"\u0e8a",
"\u0e8d",
"\u0e94"-"\u0e97",
"\u0e99"-"\u0e9f",
"\u0ea1"-"\u0ea3",
"\u0ea5",
"\u0ea7",
"\u0eaa"-"\u0eab",
"\u0ead"-"\u0eb0",
"\u0eb2"-"\u0eb3",
"\u0ebd",
"\u0ec0"-"\u0ec4",
"\u0ec6",
"\u0edc"-"\u0edd",
"\u0f00",
"\u0f40"-"\u0f47",
"\u0f49"-"\u0f6a",
"\u0f88"-"\u0f8b",
"\u1000"-"\u1021",
"\u1023"-"\u1027",
"\u1029"-"\u102a",
"\u1050"-"\u1055",
"\u10a0"-"\u10c5",
"\u10d0"-"\u10f6",
"\u1100"-"\u1159",
"\u115f"-"\u11a2",
"\u11a8"-"\u11f9",
"\u1200"-"\u1206",
"\u1208"-"\u1246",
"\u1248",
"\u124a"-"\u124d",
"\u1250"-"\u1256",
"\u1258",
"\u125a"-"\u125d",
"\u1260"-"\u1286",
"\u1288",
"\u128a"-"\u128d",
"\u1290"-"\u12ae",
"\u12b0",
"\u12b2"-"\u12b5",
"\u12b8"-"\u12be",
"\u12c0",
"\u12c2"-"\u12c5",
"\u12c8"-"\u12ce",
"\u12d0"-"\u12d6",
"\u12d8"-"\u12ee",
"\u12f0"-"\u130e",
"\u1310",
"\u1312"-"\u1315",
"\u1318"-"\u131e",
"\u1320"-"\u1346",
"\u1348"-"\u135a",
"\u13a0"-"\u13f4",
"\u1401"-"\u166c",
"\u166f"-"\u1676",
"\u1681"-"\u169a",
"\u16a0"-"\u16ea",
"\u1780"-"\u17b3",
"\u17db",
"\u1820"-"\u1877",
"\u1880"-"\u18a8",
"\u1e00"-"\u1e9b",
"\u1ea0"-"\u1ef9",
"\u1f00"-"\u1f15",
"\u1f18"-"\u1f1d",
"\u1f20"-"\u1f45",
"\u1f48"-"\u1f4d",
"\u1f50"-"\u1f57",
"\u1f59",
"\u1f5b",
"\u1f5d",
"\u1f5f"-"\u1f7d",
"\u1f80"-"\u1fb4",
"\u1fb6"-"\u1fbc",
"\u1fbe",
"\u1fc2"-"\u1fc4",
"\u1fc6"-"\u1fcc",
"\u1fd0"-"\u1fd3",
"\u1fd6"-"\u1fdb",
"\u1fe0"-"\u1fec",
"\u1ff2"-"\u1ff4",
"\u1ff6"-"\u1ffc",
"\u203f"-"\u2040",
"\u207f",
"\u20a0"-"\u20af",
"\u2102",
"\u2107",
"\u210a"-"\u2113",
"\u2115",
"\u2119"-"\u211d",
"\u2124",
"\u2126",
"\u2128",
"\u212a"-"\u212d",
"\u212f"-"\u2131",
"\u2133"-"\u2139",
"\u2160"-"\u2183",
"\u3005"-"\u3007",
"\u3021"-"\u3029",
"\u3031"-"\u3035",
"\u3038"-"\u303a",
"\u3041"-"\u3094",
"\u309d"-"\u309e",
"\u30a1"-"\u30fe",
"\u3105"-"\u312c",
"\u3131"-"\u318e",
"\u31a0"-"\u31b7",
"\u3400"-"\u4db5",
"\u4e00"-"\u9fa5",
"\ua000"-"\ua48c",
"\uac00"-"\ud7a3",
"\uf900"-"\ufa2d",
"\ufb00"-"\ufb06",
"\ufb13"-"\ufb17",
"\ufb1d",
"\ufb1f"-"\ufb28",
"\ufb2a"-"\ufb36",
"\ufb38"-"\ufb3c",
"\ufb3e",
"\ufb40"-"\ufb41",
"\ufb43"-"\ufb44",
"\ufb46"-"\ufbb1",
"\ufbd3"-"\ufd3d",
"\ufd50"-"\ufd8f",
"\ufd92"-"\ufdc7",
"\ufdf0"-"\ufdfb",
"\ufe33"-"\ufe34",
"\ufe4d"-"\ufe4f",
"\ufe69",
"\ufe70"-"\ufe72",
"\ufe74",
"\ufe76"-"\ufefc",
"\uff04",
"\uff21"-"\uff3a",
"\uff3f",
"\uff41"-"\uff5a",
"\uff65"-"\uffbe",
"\uffc2"-"\uffc7",
"\uffca"-"\uffcf",
"\uffd2"-"\uffd7",
"\uffda"-"\uffdc",
"\uffe0"-"\uffe1",
"\uffe5"-"\uffe6" ] >
}
TOKEN : {
< ALNUM_PART : [
"!",
"$",
"0"-"9",
"A"-"Z",
"_",
"a"-"z",
// Javaport: All chars for which Character.isUnicodeIdentifierPart(char) is true.
// Sadly, C++ hasn't kept up with Unicode. Though more recent, this too isn't
// up to the latest Unicode, which of course, is subject to change without notice.
"\u007f"-"\u009f",
"\u00a2"-"\u00a5",
"\u00aa",
"\u00b5",
"\u00ba",
"\u00c0"-"\u00d6",
"\u00d8"-"\u00f6",
"\u00f8"-"\u021f",
"\u0222"-"\u0233",
"\u0250"-"\u02ad",
"\u02b0"-"\u02b8",
"\u02bb"-"\u02c1",
"\u02d0"-"\u02d1",
"\u02e0"-"\u02e4",
"\u02ee",
"\u0300"-"\u034e",
"\u0360"-"\u0362",
"\u037a",
"\u0386",
"\u0388"-"\u038a",
"\u038c",
"\u038e"-"\u03a1",
"\u03a3"-"\u03ce",
"\u03d0"-"\u03d7",
"\u03da"-"\u03f3",
"\u0400"-"\u0481",
"\u0483"-"\u0486",
"\u048c"-"\u04c4",
"\u04c7"-"\u04c8",
"\u04cb"-"\u04cc",
"\u04d0"-"\u04f5",
"\u04f8"-"\u04f9",
"\u0531"-"\u0556",
"\u0559",
"\u0561"-"\u0587",
"\u0591"-"\u05a1",
"\u05a3"-"\u05b9",
"\u05bb"-"\u05bd",
"\u05bf",
"\u05c1"-"\u05c2",
"\u05c4",
"\u05d0"-"\u05ea",
"\u05f0"-"\u05f2",
"\u0621"-"\u063a",
"\u0640"-"\u0655",
"\u0660"-"\u0669",
"\u0670"-"\u06d3",
"\u06d5"-"\u06dc",
"\u06df"-"\u06e8",
"\u06ea"-"\u06ed",
"\u06f0"-"\u06fc",
"\u070f"-"\u072c",
"\u0730"-"\u074a",
"\u0780"-"\u07b0",
"\u0901"-"\u0903",
"\u0905"-"\u0939",
"\u093c"-"\u094d",
"\u0950"-"\u0954",
"\u0958"-"\u0963",
"\u0966"-"\u096f",
"\u0981"-"\u0983",
"\u0985"-"\u098c",
"\u098f"-"\u0990",
"\u0993"-"\u09a8",
"\u09aa"-"\u09b0",
"\u09b2",
"\u09b6"-"\u09b9",
"\u09bc",
"\u09be"-"\u09c4",
"\u09c7"-"\u09c8",
"\u09cb"-"\u09cd",
"\u09d7",
"\u09dc"-"\u09dd",
"\u09df"-"\u09e3",
"\u09e6"-"\u09f3",
"\u0a02",
"\u0a05"-"\u0a0a",
"\u0a0f"-"\u0a10",
"\u0a13"-"\u0a28",
"\u0a2a"-"\u0a30",
"\u0a32"-"\u0a33",
"\u0a35"-"\u0a36",
"\u0a38"-"\u0a39",
"\u0a3c",
"\u0a3e"-"\u0a42",
"\u0a47"-"\u0a48",
"\u0a4b"-"\u0a4d",
"\u0a59"-"\u0a5c",
"\u0a5e",
"\u0a66"-"\u0a74",
"\u0a81"-"\u0a83",
"\u0a85"-"\u0a8b",
"\u0a8d",
"\u0a8f"-"\u0a91",
"\u0a93"-"\u0aa8",
"\u0aaa"-"\u0ab0",
"\u0ab2"-"\u0ab3",
"\u0ab5"-"\u0ab9",
"\u0abc"-"\u0ac5",
"\u0ac7"-"\u0ac9",
"\u0acb"-"\u0acd",
"\u0ad0",
"\u0ae0",
"\u0ae6"-"\u0aef",
"\u0b01"-"\u0b03",
"\u0b05"-"\u0b0c",
"\u0b0f"-"\u0b10",
"\u0b13"-"\u0b28",
"\u0b2a"-"\u0b30",
"\u0b32"-"\u0b33",
"\u0b36"-"\u0b39",
"\u0b3c"-"\u0b43",
"\u0b47"-"\u0b48",
"\u0b4b"-"\u0b4d",
"\u0b56"-"\u0b57",
"\u0b5c"-"\u0b5d",
"\u0b5f"-"\u0b61",
"\u0b66"-"\u0b6f",
"\u0b82"-"\u0b83",
"\u0b85"-"\u0b8a",
"\u0b8e"-"\u0b90",
"\u0b92"-"\u0b95",
"\u0b99"-"\u0b9a",
"\u0b9c",
"\u0b9e"-"\u0b9f",
"\u0ba3"-"\u0ba4",
"\u0ba8"-"\u0baa",
"\u0bae"-"\u0bb5",
"\u0bb7"-"\u0bb9",
"\u0bbe"-"\u0bc2",
"\u0bc6"-"\u0bc8",
"\u0bca"-"\u0bcd",
"\u0bd7",
"\u0be7"-"\u0bef",
"\u0c01"-"\u0c03",
"\u0c05"-"\u0c0c",
"\u0c0e"-"\u0c10",
"\u0c12"-"\u0c28",
"\u0c2a"-"\u0c33",
"\u0c35"-"\u0c39",
"\u0c3e"-"\u0c44",
"\u0c46"-"\u0c48",
"\u0c4a"-"\u0c4d",
"\u0c55"-"\u0c56",
"\u0c60"-"\u0c61",
"\u0c66"-"\u0c6f",
"\u0c82"-"\u0c83",
"\u0c85"-"\u0c8c",
"\u0c8e"-"\u0c90",
"\u0c92"-"\u0ca8",
"\u0caa"-"\u0cb3",
"\u0cb5"-"\u0cb9",
"\u0cbe"-"\u0cc4",
"\u0cc6"-"\u0cc8",
"\u0cca"-"\u0ccd",
"\u0cd5"-"\u0cd6",
"\u0cde",
"\u0ce0"-"\u0ce1",
"\u0ce6"-"\u0cef",
"\u0d02"-"\u0d03",
"\u0d05"-"\u0d0c",
"\u0d0e"-"\u0d10",
"\u0d12"-"\u0d28",
"\u0d2a"-"\u0d39",
"\u0d3e"-"\u0d43",
"\u0d46"-"\u0d48",
"\u0d4a"-"\u0d4d",
"\u0d57",
"\u0d60"-"\u0d61",
"\u0d66"-"\u0d6f",
"\u0d82"-"\u0d83",
"\u0d85"-"\u0d96",
"\u0d9a"-"\u0db1",
"\u0db3"-"\u0dbb",
"\u0dbd",
"\u0dc0"-"\u0dc6",
"\u0dca",
"\u0dcf"-"\u0dd4",
"\u0dd6",
"\u0dd8"-"\u0ddf",
"\u0df2"-"\u0df3",
"\u0e01"-"\u0e3a",
"\u0e3f"-"\u0e4e",
"\u0e50"-"\u0e59",
"\u0e81"-"\u0e82",
"\u0e84",
"\u0e87"-"\u0e88",
"\u0e8a",
"\u0e8d",
"\u0e94"-"\u0e97",
"\u0e99"-"\u0e9f",
"\u0ea1"-"\u0ea3",
"\u0ea5",
"\u0ea7",
"\u0eaa"-"\u0eab",
"\u0ead"-"\u0eb9",
"\u0ebb"-"\u0ebd",
"\u0ec0"-"\u0ec4",
"\u0ec6",
"\u0ec8"-"\u0ecd",
"\u0ed0"-"\u0ed9",
"\u0edc"-"\u0edd",
"\u0f00",
"\u0f18"-"\u0f19",
"\u0f20"-"\u0f29",
"\u0f35",
"\u0f37",
"\u0f39",
"\u0f3e"-"\u0f47",
"\u0f49"-"\u0f6a",
"\u0f71"-"\u0f84",
"\u0f86"-"\u0f8b",
"\u0f90"-"\u0f97",
"\u0f99"-"\u0fbc",
"\u0fc6",
"\u1000"-"\u1021",
"\u1023"-"\u1027",
"\u1029"-"\u102a",
"\u102c"-"\u1032",
"\u1036"-"\u1039",
"\u1040"-"\u1049",
"\u1050"-"\u1059",
"\u10a0"-"\u10c5",
"\u10d0"-"\u10f6",
"\u1100"-"\u1159",
"\u115f"-"\u11a2",
"\u11a8"-"\u11f9",
"\u1200"-"\u1206",
"\u1208"-"\u1246",
"\u1248",
"\u124a"-"\u124d",
"\u1250"-"\u1256",
"\u1258",
"\u125a"-"\u125d",
"\u1260"-"\u1286",
"\u1288",
"\u128a"-"\u128d",
"\u1290"-"\u12ae",
"\u12b0",
"\u12b2"-"\u12b5",
"\u12b8"-"\u12be",
"\u12c0",
"\u12c2"-"\u12c5",
"\u12c8"-"\u12ce",
"\u12d0"-"\u12d6",
"\u12d8"-"\u12ee",
"\u12f0"-"\u130e",
"\u1310",
"\u1312"-"\u1315",
"\u1318"-"\u131e",
"\u1320"-"\u1346",
"\u1348"-"\u135a",
"\u1369"-"\u1371",
"\u13a0"-"\u13f4",
"\u1401"-"\u166c",
"\u166f"-"\u1676",
"\u1681"-"\u169a",
"\u16a0"-"\u16ea",
"\u1780"-"\u17d3",
"\u17db",
"\u17e0"-"\u17e9",
"\u180b"-"\u180e",
"\u1810"-"\u1819",
"\u1820"-"\u1877",
"\u1880"-"\u18a9",
"\u1e00"-"\u1e9b",
"\u1ea0"-"\u1ef9",
"\u1f00"-"\u1f15",
"\u1f18"-"\u1f1d",
"\u1f20"-"\u1f45",
"\u1f48"-"\u1f4d",
"\u1f50"-"\u1f57",
"\u1f59",
"\u1f5b",
"\u1f5d",
"\u1f5f"-"\u1f7d",
"\u1f80"-"\u1fb4",
"\u1fb6"-"\u1fbc",
"\u1fbe",
"\u1fc2"-"\u1fc4",
"\u1fc6"-"\u1fcc",
"\u1fd0"-"\u1fd3",
"\u1fd6"-"\u1fdb",
"\u1fe0"-"\u1fec",
"\u1ff2"-"\u1ff4",
"\u1ff6"-"\u1ffc",
"\u200c"-"\u200f",
"\u202a"-"\u202e",
"\u203f"-"\u2040",
"\u206a"-"\u206f",
"\u207f",
"\u20a0"-"\u20af",
"\u20d0"-"\u20dc",
"\u20e1",
"\u2102",
"\u2107",
"\u210a"-"\u2113",
"\u2115",
"\u2119"-"\u211d",
"\u2124",
"\u2126",
"\u2128",
"\u212a"-"\u212d",
"\u212f"-"\u2131",
"\u2133"-"\u2139",
"\u2160"-"\u2183",
"\u3005"-"\u3007",
"\u3021"-"\u302f",
"\u3031"-"\u3035",
"\u3038"-"\u303a",
"\u3041"-"\u3094",
"\u3099"-"\u309a",
"\u309d"-"\u309e",
"\u30a1"-"\u30fe",
"\u3105"-"\u312c",
"\u3131"-"\u318e",
"\u31a0"-"\u31b7",
"\u3400"-"\u4db5",
"\u4e00"-"\u9fa5",
"\ua000"-"\ua48c",
"\uac00"-"\ud7a3",
"\uf900"-"\ufa2d",
"\ufb00"-"\ufb06",
"\ufb13"-"\ufb17",
"\ufb1d"-"\ufb28",
"\ufb2a"-"\ufb36",
"\ufb38"-"\ufb3c",
"\ufb3e",
"\ufb40"-"\ufb41",
"\ufb43"-"\ufb44",
"\ufb46"-"\ufbb1",
"\ufbd3"-"\ufd3d",
"\ufd50"-"\ufd8f",
"\ufd92"-"\ufdc7",
"\ufdf0"-"\ufdfb",
"\ufe20"-"\ufe23",
"\ufe33"-"\ufe34",
"\ufe4d"-"\ufe4f",
"\ufe69",
"\ufe70"-"\ufe72",
"\ufe74",
"\ufe76"-"\ufefc",
"\ufeff",
"\uff04",
"\uff10"-"\uff19",
"\uff21"-"\uff3a",
"\uff3f",
"\uff41"-"\uff5a",
"\uff65"-"\uffbe",
"\uffc2"-"\uffc7",
"\uffca"-"\uffcf",
"\uffd2"-"\uffd7",
"\uffda"-"\uffdc",
"\uffe0"-"\uffe1",
"\uffe5"-"\uffe6",
"\ufff9"-"\ufffb" ] >
}
TOKEN : { /* NO MATCH */
< ERROR : ~[] >
}
void FormCalculation() : {
}
{
{
//
// No expressions parsed: emit a "no expression encountered" error.
//
MsgFormatPos sErr = new MsgFormatPos(ResId.FC_ERR_NO_EXPR);
CalcSymbol oSym = new CalcSymbol(sErr.toString(), true, 0, 0);
mStack.push(oSym);
}
| {
yyError(ResId.FC_ERR_SYNTAX);
}
| {
//
// Generate code for entry of outermost scope
// provided we've not cached anything yet.
//
if (! mbInSaveMode || mnSavedDecl == 0) {
generate(Instruction.gEnter);
generate(Integer.valueOf(1));
}
moScope.setActive(1);
setLine();
}
ExpressionList() {
yyTrace("FormCalculation: ExpressionList");
//
// Generate code for exit of outermost scope
// and stoppage of this execution thread.
//
generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
generate(Instruction.gStop);
}
}
int ExpressionList() : {
int $$;
}
{
$$ = Expression() {
yyTrace("ExpressionList: Expression");
}
(
LOOKAHEAD(Expression()) {
generate(Instruction.gDeref);
setLine();
}
$$ = Expression() {
yyTrace("ExpressionList: ExpressionList Expression");
//
// Generate code for evaluation of expression list.
//
generate(Instruction.gList);
}
)* {
return $$;
}
}
int Var() : {
int $$ = moCode.generate();
}
{
{
if (mbInVarDeclaration)
yyError(ResId.FC_ERR_SYNTAX);
mbInVarDeclaration = true;
if (moScope.isGlobal()) {
//
// Generate code for labelling of global variable.
//
$$ = generate(Instruction.gGbl);
generate(Instruction.gStop);
}
}
{
return $$;
}
}
CalcSymbol Variable() : {
String $1;
}
{
$1 = Identifier() {
yyTrace("Variable: Identifier");
setLine();
CalcSymbol oSym = null;
String sParam = msFunc;
sParam += $1;
if ((oSym = varExists($1, moScope)) != null) {
// IsGlobal always returns false? Can we ever have global script?
if (! moScope.isGlobal() || ! mbAllowDups)
yyError(ResId.FC_ERR_VAR_DUP);
else {
//
// Generate code for loading value of variable.
//
generate(Instruction.gLoad);
generate(oSym);
}
}
// watson bug 1352985 if we have params don't call VarExists
else if (mbInFuncParameters) {
//
// Set attributes of this formal parameter's symbol table entry.
//
oSym = moData.install(sParam);
oSym.setType(CalcSymbol.TypeParameter);
oSym.setStore(CalcSymbol.StoreFroz | CalcSymbol.StorePrelim);
}
else if (mbInFuncDeclaration && (oSym = varExists(sParam, moScope)) != null) {
// IsGlobal always returns false? Can we ever have global script?
if (! moScope.isGlobal() || ! mbAllowDups)
yyError(ResId.FC_ERR_VAR_DUP);
else {
//
// Generate code for loading value of variable.
//
generate(Instruction.gLoad);
generate(oSym);
}
}
else if (mbInForeachLoop || mbInLoopDeclaration || mbInVarDeclaration) {
//
// Set attributes of this variable's symbol table entry.
//
oSym = moData.install($1);
oSym.setType(CalcSymbol.TypeVariable);
oSym.setScope(moScope.getScope());
oSym.setStringValue("");
if (mbInFuncDeclaration)
oSym.setStore(CalcSymbol.StoreFroz | CalcSymbol.StorePrelim);
else
oSym.setStore(CalcSymbol.StorePerm | CalcSymbol.StorePrelim);
//
// Generate code for loading value of variable.
//
generate(Instruction.gLoad);
generate(oSym);
}
return oSym;
}
}
int EndVar() : {
}
{
{
mbInVarDeclaration = false;
return moCode.generate();
}
}
int Func() : {
int $$;
}
{
{
if (mbInFuncDeclaration)
yyError(ResId.FC_ERR_SYNTAX);
if (! moScope.isGlobal())
yyError(ResId.FC_ERR_FUNC_DECL);
mbInFuncDeclaration = true;
msFunc = "";
//
// Generate code for declaration of function.
//
$$ = generate(Instruction.gFunc);
generate(Instruction.gStop);
generate(Instruction.gStop);
return $$;
}
}
CalcSymbol Function() : {
CalcSymbol $$;
String $1;
}
{
$1 = Identifier() {
yyTrace("Function: Identifier");
//
// Upcase the identifier, and
//
StringBuilder sFunction = new StringBuilder($1);
for (int i = 0; i < sFunction.length(); i++) {
char c = sFunction.charAt(i);
if ('a' <= c && c <= 'z')
sFunction.setCharAt(i, (char) (c & ~0x20));
}
//
// Check if its the name of a builtin function.
//
CalcSymbol oSym = mBuiltin.lookup(sFunction.toString());
//
// If not Then check if its the name of a user-defined function.
//
if (oSym == null)
oSym = moData.lookup($1);
if (oSym != null) {
if (oSym.getType() == CalcSymbol.TypeBuiltin)
yyError(ResId.FC_ERR_FUNC_USED);
if (oSym.getType() == CalcSymbol.TypeFunction && ! mbAllowDups)
yyError(ResId.FC_ERR_FUNC_DUP);
msFunc = oSym.getName();
}
else {
msFunc = $1;
//
// Set attributes of this function's symbol table entry.
//
oSym = moData.install($1);
oSym.setType(CalcSymbol.TypeFunction);
oSym.setStore(CalcSymbol.StoreFroz | CalcSymbol.StorePrelim);
oSym.setAddr(0);
oSym.setCntValue(0);
}
msFunc += '`';
$$ = oSym;
//
// Generate code for entry to new scope.
//
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
}
{
return $$;
}
}
int Parameters() : {
int $$;
}
{
{
mbInFuncParameters = true;
}
(
$$ = ParameterList()
| {
yyTrace("ParameterList:");
$$ = 0;
}
) {
mbInFuncParameters = false;
return $$;
}
}
int ParameterList() : {
int $$;
CalcSymbol $1, $3;
}
{
$1 = Variable() {
yyTrace("ParameterList: Variable");
$$ = 1;
//
// Set attribute of this formal parameter's symbol table entry.
//
if ($1 != null)
$1.setIdxValue($$);
}
(
$3 = Variable() {
yyTrace("ParameterList: ParameterList , Variable");
$$ += 1;
//
// Set attribute of this formal parameter's symbol table entry.
//
if ($3 != null)
$3.setIdxValue($$);
}
)* {
return $$;
}
}
int EndFunc() : {
int $$;
}
{
{
mbInFuncDeclaration = false;
msFunc = "";
//
// Generate code for exit of current scope.
//
generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
//
// Generate code for return from function call.
//
$$ = generate(Instruction.gRet);
return $$;
}
}
int Expression() : {
int $$;
}
{
(
$$ = DeclarationExpression() {
yyTrace("Expression: DeclarationExpression");
}
| LOOKAHEAD(AssignmentExpression()) $$ = AssignmentExpression() {
yyTrace("Expression: AssignmentSimpleExpression");
}
| $$ = BreakExpression() {
yyTrace("Expression: ContinueExpression");
}
| $$ = ContinueExpression() {
yyTrace("Expression: ContinueExpression");
}
| $$ = BlockExpression() {
yyTrace("Expression: BlockExpression");
}
| $$ = ForeachExpression() {
yyTrace("Expression: ForeachExpression");
}
| $$ = ForExpression() {
yyTrace("Expression: ForExpression");
}
| $$ = WhileExpression() {
yyTrace("Expression: WhileExpression");
}
| LOOKAHEAD(IfExpression()) $$ = IfExpression() {
yyTrace("Expression: IfExpression");
}
| $$ = SimpleExpression() {
yyTrace("Expression: SimpleExpression");
}
) {
return $$;
}
}
int DeclarationExpression() : {
int $$;
int $1, $3, $5, $10;
CalcSymbol $2;
int nDecl;
}
{
LOOKAHEAD(3) $1 = Var() Variable() SimpleExpression() EndVar() {
yyTrace("DeclarationExpression: Var Variable = SimpleExpression");
//
// Generate code for assignment to variable.
//
generate(Instruction.gAsgn);
//
// Backfix address part of any Gbl instruction.
// Address is the relative offset within
// instruction memory of EndVar - Var.
//
if (moScope.isGlobal()) {
$5 = moCode.generate();
nDecl = moCode.getCodeStart() + $1;
moCode.moCodeBase[nDecl + 1] = Integer.valueOf($5 - $1); // endvar part
}
$$ = $1;
return $$;
}
| $1 = Var() Variable() EndVar() {
yyTrace("DeclarationExpression: Var Variable");
//
// Generate code for loading of the default value.
// This symbol lives in instruction memory.
//
CalcSymbol oSym = new CalcSymbol("");
oSym.setStore(CalcSymbol.StorePerm);
generate(Instruction.gLoad);
generate(oSym);
//
// Generate code for assignment to variable.
//
generate(Instruction.gAsgn);
//
// Backfix address part of any Gbl instruction.
// Address is the relative offset within
// instruction memory of EndVar - Var.
//
if (moScope.isGlobal()) {
$3 = moCode.generate();
nDecl = moCode.getCodeStart() + $1;
moCode.moCodeBase[nDecl + 1] = Integer.valueOf($3 - $1); // endvar part
}
$$ = $1;
return $$;
}
| $1 = Func() $2 = Function() $5 = Parameters() ExpressionList() $10 = EndFunc() {
yyTrace("DeclarationExpression: Func Function ( ParameterList ) Do EndFunc");
//
// Backfix name and address parts of Func instruction.
// Name is a symbol containing the functions' name.
// This symbol lives in instruction memory.
// Address is the relative of offset within
// instruction memory of EndFunc - Func.
//
nDecl = moCode.getCodeStart() + $1;
moCode.moCodeBase[nDecl + 1] = $2; // function
moCode.moCodeBase[nDecl + 2] = Integer.valueOf($10 - $1 + 1); // endfunc part
//
// Set attributes of this function's symbol table entry.
//
if ($2.getType() == CalcSymbol.TypeFunction) {
$2.setAddr($1);
$2.setCntValue($5);
}
$$ = $1;
return $$;
}
}
int AssignmentExpression() : {
int $$;
int $1;
}
{
$1 = Accessor() SimpleExpression() {
yyTrace("AssignmentExpression: Accessor = SimpleExpression");
//
// Generate code for assignment to accessor.
//
generate(Instruction.gAsgn);
$$ = $1;
return $$;
}
}
int BlockExpression() : {
int $$;
}
{
{
//
// Generate code for entry of new scope of block expression.
//
$$ = generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
} ExpressionList() {
yyTrace("BlockExpression: Do ExpressionList End");
//
// Generate code for exit of current scope
// at end of block expression.
//
$$ = generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
return $$;
}
}
int Foreach() : {
int $$;
}
{
{
//
// Generate code for foreach instruction.
//
$$ = mnLoopOffset = generate(Instruction.gForeach);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
//
// Generate code for entry of new scope.
//
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
mbInForeachLoop = true;
} Variable() {
//
// Generate code for assignment of foreach variable
// and stoppage of this execution thread.
//
generate(Instruction.gAsgn2);
generate(Instruction.gStop);
return $$;
}
}
int In() : {
}
{
{
return moCode.generate();
}
}
int Arguments() : {
int $$;
}
{
(
$$ = ArgumentList()
| {
yyTrace("ArgumentList:");
if (mbInForeachLoop)
yyError(ResId.FC_ERR_LOOP_ARGS);
$$ = 0;
}
) {
return $$;
}
}
int ArgumentList() : {
int $$;
}
{
SimpleExpression() {
yyTrace("ArgumentList: SimpleExpression");
generate(Instruction.gNoop);
$$ = 1;
}
(
SimpleExpression() {
yyTrace("ArgumentList: ArgumentList , SimpleExpression");
$$ += 1;
}
)* {
return $$;
}
}
int Do() : {
int $$;
}
{
{
//
// Generate code for stoppage of this execution thread.
//
$$ = generate(Instruction.gStop);
//
// Generate code for entry of new scope of while expression
// or function declaration.
//
if (! mbInLoopDeclaration && ! mbInForeachLoop) {
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
}
return $$;
}
}
int EndFor() : {
int $$;
}
{
{
//
// Generate code for stoppage of this execution thread.
//
generate(Instruction.gStop);
//
// Generate code for exit of current scope
// at end of for and foreach expressions.
//
$$ = generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
return $$;
}
}
int ForeachExpression() : {
int $$;
int $1, $2, $4, $6, $9;
}
{
$1 = Foreach() $2 = In() $4 = Arguments() {
if ($4 == 0 && mbInForeachLoop)
yyError(ResId.FC_ERR_LOOP_ARGS);
}
$6 = Do() {
mbInForeachLoop = false;
} ExpressionList() $9 = EndFor() {
yyTrace("ForeachExpression: Foreach Do EndFor");
//
// Backfix argument count and address parts of
// a Foreach instruction.
//
int nFor = moCode.getCodeStart() + $1;
moCode.moCodeBase[nFor + 1] = Integer.valueOf($4); // arg count
moCode.moCodeBase[nFor + 2] = Integer.valueOf($2 - $1); // list part
moCode.moCodeBase[nFor + 3] = Integer.valueOf($6 - $1 + 1); // do part
moCode.moCodeBase[nFor + 4] = Integer.valueOf($9 - $1); // endfor part
$$ = $1;
return $$;
}
}
int For() : {
int $$;
int $2;
}
{
{
//
// Generate code for for instruction.
//
$2 = mnLoopOffset = generate(Instruction.gFor);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
//
// Generate code for entry of new scope.
//
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
mbInLoopDeclaration = true;
} Variable() SimpleExpression() {
//
// Generate code for assignment of for loop variable
// and stoppage of this execution thread.
//
generate(Instruction.gAsgn);
generate(Instruction.gStop);
$$ = $2;
return $$;
}
}
int To() : {
int $$;
int $2;
}
{
{
mbInDowntoLoop = false;
$2 = moCode.generate();
} SimpleExpression() {
//
// Generate code for less_than_or_equal instruction
// and stoppage of this execution thread.
//
generate(Instruction.gLe);
generate(Instruction.gStop);
$$ = $2;
return $$;
}
| {
mbInDowntoLoop = true;
$2 = moCode.generate();
} SimpleExpression() {
//
// Generate code for greater_than_or_equal instruction
// and stoppage of this execution thread.
//
generate(Instruction.gGe);
generate(Instruction.gStop);
$$ = $2;
return $$;
}
}
int Step() : {
int $$;
int $2;
int nForVar;
}
{
{
//
// Generate code for twice loading of for loop variable.
//
nForVar = moCode.getCodeStart() + mnLoopOffset + 8;
$2 = generate(Instruction.gLoad);
generate(moCode.moCodeBase[nForVar]);
generate(Instruction.gLoad);
generate(moCode.moCodeBase[nForVar]);
} SimpleExpression() {
//
// Generate code for sub/add instruction followed
// by assignment to for loop variable.
//
if (mbInDowntoLoop)
generate(Instruction.gSub);
else
generate(Instruction.gAdd);
generate(Instruction.gAsgn);
$$ = $2;
return $$;
}
| {
//
// Generate code for twice loading of for loop variable.
//
nForVar = moCode.getCodeStart() + mnLoopOffset + 8;
$$ = generate(Instruction.gLoad);
generate(moCode.moCodeBase[nForVar]);
generate(Instruction.gLoad);
generate(moCode.moCodeBase[nForVar]);
//
// Generate code for loading default step value.
//
CalcSymbol oSym = new CalcSymbol(1);
oSym.setStore(CalcSymbol.StorePerm);
generate(Instruction.gLoad);
generate(oSym);
//
// Generate code for sub/add instruction followed
// by assignment to for loop variable.
//
if (mbInDowntoLoop)
generate(Instruction.gSub);
else
generate(Instruction.gAdd);
generate(Instruction.gAsgn);
return $$;
}
}
int ForExpression() : {
int $$;
int $1, $2, $3, $4, $7;
}
{
$1 = For() $2 = To() $3 = Step() $4 = Do() {
mbInLoopDeclaration = false;
} ExpressionList() $7 = EndFor() {
yyTrace("ForExpression: For Do EndFor");
//
// Backfix address parts of For a instruction.
//
int nFor = moCode.getCodeStart() + $1;
moCode.moCodeBase[nFor + 1] = Integer.valueOf($2 - $1); // to part
moCode.moCodeBase[nFor + 2] = Integer.valueOf($3 - $1); // step part
moCode.moCodeBase[nFor + 3] = Integer.valueOf($4 - $1 + 1); // do part
moCode.moCodeBase[nFor + 4] = Integer.valueOf($7 - $1); // endfor part
$$ = $1;
return $$;
}
}
int While() : {
int $$;
}
{
{
//
// Generate code for while instruction.
//
$$ = mnLoopOffset = generate(Instruction.gWhile);
generate(Instruction.gStop);
generate(Instruction.gStop);
return $$;
}
}
int Condition() : {
int $$;
int $2;
}
{
$2 = SimpleExpression() {
yyTrace("Condition: ( SimpleExpression )");
$$ = $2;
return $$;
}
}
int EndWhile() : {
int $$;
}
{
{
//
// Generate code for stoppage of this execution thread,
// and for exit of current scope.
//
$$ = generate(Instruction.gStop);
generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
return $$;
}
}
int WhileExpression() : {
int $$;
int $1, $3, $5;
}
{
$1 = While() Condition() $3 = Do() ExpressionList() $5 = EndWhile() {
yyTrace("WhileExpression: While Do EndWhile");
//
// Backfix address parts of a While instruction.
//
int nWhile = moCode.getCodeStart() + $1;
moCode.moCodeBase[nWhile + 1] = Integer.valueOf($3 - $1 + 1); // do part
moCode.moCodeBase[nWhile + 2] = Integer.valueOf($5 - $1 + 1); // endwhile part
$$ = $1;
return $$;
}
}
int If() : {
int $$;
}
{
{
//
// Generate code for if instruction.
//
$$ = generate(Instruction.gIf);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
return $$;
}
}
int Then() : {
int $$;
}
{
{
//
// Generate code for stoppage of preceeding
// execution thread and entry to new scope.
//
$$ = generate(Instruction.gStop);
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
setLine();
return $$;
}
}
int Elif() : {
int $$;
}
{
{
//
// Generate code for exit of current scope.
//
generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
//
// Generate code for stoppage of preceeding execution thread.
//
$$ = generate(Instruction.gStop);
//
// Generate code for if instruction.
//
generate(Instruction.gIf);
generate(Instruction.gStop);
generate(Instruction.gStop);
generate(Instruction.gStop);
return $$;
}
}
int Else() : {
int $$;
}
{
{
//
// Generate code for exit of current scope.
//
generate(Instruction.gExit);
generate(Integer.valueOf( moScope.exit()));
//
// Generate code for stoppage of preceeding execution thread.
//
$$ = generate(Instruction.gStop);
//
// Generate code for entry of new scope.
//
generate(Instruction.gEnter);
generate(Integer.valueOf(moScope.enter()));
return $$;
}
}
int EndIf() : {
int $$;
}
{
{
//
// Generate code for exit of current scope.
//
generate(Instruction.gExit);
generate(Integer.valueOf(moScope.exit()));
//
// Generate code for stoppage of preceeding execution thread.
//
$$ = generate(Instruction.gStop);
return $$;
}
}
int IfExpression() : {
int $1, $3, $5 = -1, $7;
}
{
LOOKAHEAD(If() Condition() Then() ExpressionList() ElifExpression())
$1 = If() Condition() $3 = Then() ExpressionList() $5 = ElifExpression() {
yyTrace("IfExpression: If Then ElseIf");
//
// Backfix address parts of an If instruction.
//
int nIf = moCode.getCodeStart() + $1;
int nElif = moCode.getCodeStart() + $5 + 1;
assert(moCode.moCodeBase[nElif + 3] instanceof Integer);
nElif = ((Integer) moCode.moCodeBase[nElif + 3]).intValue();
moCode.moCodeBase[nIf + 1] = Integer.valueOf($3 - $1 + 1); // then part
moCode.moCodeBase[nIf + 2] = Integer.valueOf($5 - $1 + 1); // else part
moCode.moCodeBase[nIf + 3] = Integer.valueOf(nElif + $5 - $1 + 2); // endif part
return $1;
}
| $1 = If() Condition() $3 = Then() ExpressionList() [ $5 = Else() ExpressionList() ] $7 = EndIf() {
yyTrace("IfExpression: If Then Else Endif");
int nIf = moCode.getCodeStart() + $1;
moCode.moCodeBase[nIf + 1] = Integer.valueOf($3 - $1 + 1); // then part
if ($5 >= 0)
moCode.moCodeBase[nIf + 2] = Integer.valueOf($5 - $1 + 1); // else part
moCode.moCodeBase[nIf + 3] = Integer.valueOf($7 - $1 + 1); // endif part
return $1;
}
}
int ElifExpression() : {
int $1, $3, $5 = -1, $7;
}
{
LOOKAHEAD(Elif() Condition() Then() ExpressionList() ElifExpression())
$1 = Elif() Condition() $3 = Then() ExpressionList() $5 = ElifExpression() {
yyTrace("ElifExpression: Elseif Then Elseif");
//
// Backfix address parts of an If instruction.
//
int nIf = moCode.getCodeStart() + $1 + 1;
int nElif = moCode.getCodeStart() + $5 + 1;
assert(moCode.moCodeBase[nElif + 3] instanceof Integer);
nElif = ((Integer) moCode.moCodeBase[nElif + 3]).intValue();
moCode.moCodeBase[nIf + 1] = Integer.valueOf($3 - $1); // then part
moCode.moCodeBase[nIf + 2] = Integer.valueOf($5 - $1); // elseif part
moCode.moCodeBase[nIf + 3] = Integer.valueOf(nElif + $5 - $1); // endif part
return $1;
}
| $1 = Elif() Condition() $3 = Then() ExpressionList() [ $5 = Else() ExpressionList() ] $7 = EndIf() {
yyTrace("ElifExpression: Elseif Then Else EndIf");
//
// Backfix address parts of an If instruction.
//
int nIf = moCode.getCodeStart() + $1 + 1;
moCode.moCodeBase[nIf + 1] = Integer.valueOf($3 - $1); // then part
if ($5 >= 0)
moCode.moCodeBase[nIf + 2] = Integer.valueOf($5 - $1); // else part
moCode.moCodeBase[nIf + 3] = Integer.valueOf($7 - $1); // endif part
//
// Generate code for stoppage of this execution thread -- an else
// clause consisting of an If-Then-Else-Endif expression.
//
generate(Instruction.gStop);
return $1;
}
}
int BreakExpression() : {
}
{
{
yyTrace("BreakExpression: Break");
if (mnLoopOffset == 0)
yyError(ResId.FC_ERR_LOOP);
return generate(Instruction.gBreak);
}
}
int ContinueExpression() : {
}
{
{
yyTrace("ContinueExpression: Continue");
if (mnLoopOffset == 0)
yyError(ResId.FC_ERR_LOOP);
return generate(Instruction.gCont);
}
}
int SimpleExpression() : {
int $$;
}
{
$$ = LogicalOrExpression() {
yyTrace("LogicalOrExpression: LogicalOrExpression");
return $$;
}
}
int LogicalOrExpression() : {
int $$;
}
{
$$ = LogicalAndExpression() {
yyTrace("LogicalOrExpression: LogicalAndExpression");
}
(
Or() $$ = LogicalAndExpression() {
yyTrace("LogicalOrExpression: LogicalOrExpression | LogicalAndExpression");
generate(Instruction.gOr);
}
)* {
return $$;
}
}
int LogicalAndExpression() : {
int $$;
}
{
$$ = EqualityExpression() {
yyTrace("LogicalAndExpression: EqualityExpression");
}
(
And() $$ = EqualityExpression() {
yyTrace("LogicalAndExpression: LogicalAndExpression & EqualityExpression");
generate(Instruction.gAnd);
}
)* {
return $$;
}
}
int EqualityExpression() : {
int $$;
}
{
$$ = RelationalExpression() {
yyTrace("EqualityExpression: RelationalExpression");
}
(
Eq() $$ = RelationalExpression() {
yyTrace("EqualityExpression: EqualityExpression == RelationalExpression");
generate(Instruction.gEq);
}
| Ne() $$ = RelationalExpression() {
yyTrace("EqualityExpression: EqualityExpression <> RelationalExpression");
generate(Instruction.gNe);
}
)* {
return $$;
}
}
int RelationalExpression() : {
int $$;
}
{
$$ = AdditiveExpression() {
yyTrace("RelationalExpression: AdditiveExpression");
}
(
Gt() $$ = AdditiveExpression() {
yyTrace("RelationalExpression: RelationalExpression > AdditiveExpression");
generate(Instruction.gGt);
}
| Ge() $$ = AdditiveExpression() {
yyTrace("RelationalExpression: RelationalExpression >= AdditiveExpression");
generate(Instruction.gGe);
}
| Lt() $$ = AdditiveExpression() {
yyTrace("RelationalExpression: RelationalExpression < AdditiveExpression");
generate(Instruction.gLt);
}
| Le() $$ = AdditiveExpression() {
yyTrace("RelationalExpression: RelationalExpression <= AdditiveExpression");
generate(Instruction.gLe);
}
)* {
return $$;
}
}
int AdditiveExpression() : {
int $$;
Token $1;
}
{
$$ = MultiplicativeExpression() {
yyTrace("AdditiveExpression: MultiplicativeExpression");
}
( LOOKAHEAD( | )
( $1 = | $1 = ) $$ = MultiplicativeExpression() {
yyTrace("AdditiveExpression: AdditiveExpression - MultiplicativeExpression");
generate($1.kind == PLUS ? Instruction.gAdd : Instruction.gSub);
}
)* {
return $$;
}
}
int MultiplicativeExpression() : {
int $$;
}
{
$$ = UnaryExpression() {
yyTrace("MultiplicativeExpression: UnaryExpression");
}
(
$$ = UnaryExpression() {
yyTrace("MultiplicativeExpression: MultiplicativeExpression * UnaryExpression");
generate(Instruction.gMul);
}
| $$ = UnaryExpression() {
yyTrace("MultiplicativeExpression: MultiplicativeExpression / UnaryExpression");
generate(Instruction.gDiv);
}
)* {
return $$;
}
}
int UnaryExpression() : {
int $$;
int $1, $2;
}
{
$1 = PrimaryExpression() {
yyTrace("UnaryExpression: PrimaryExpression");
$$ = $1;
return $$;
}
| $2 = UnaryExpression() {
yyTrace("UnaryExpression: + UnaryExpression");
generate(Instruction.gUplus);
$$ = $2;
return $$;
}
| $2 = UnaryExpression() {
yyTrace("UnaryExpression: - UnaryExpression");
generate(Instruction.gUminus);
$$ = $2;
return $$;
}
| $2 = UnaryExpression() {
yyTrace("UnaryExpression: not UnaryExpression");
generate(Instruction.gNot);
$$ = $2;
return $$;
}
}
int PrimaryExpression() : {
int $$;
Token string;
double value;
CalcSymbol oSym;
}
{
Null() {
yyTrace("PrimaryExpression: NULL");
//
// Generate code for loading a null literal.
// This symbol lives in instruction memory.
//
setLine();
oSym = new CalcSymbol();
oSym.setStore(CalcSymbol.StorePerm);
$$ = generate(Instruction.gLoad);
generate(oSym);
return $$;
}
| string = {
yyTrace("PrimaryExpression: STRING");
//
// Generate code for loading a string literal.
//
setLine();
String s = FormCalcUtil.interpolate(string.image);
//
// Javaport: not possible to support the legacy behaviour here.
// Java strings won't allow it.
//
if (s == null)
yyError(ResId.FC_ERR_SURROGATE);
oSym = new CalcSymbol(s);
oSym.setStore(CalcSymbol.StorePerm);
$$ = generate(Instruction.gLoad);
generate((Object) oSym);
return $$;
}
| value = Number() {
yyTrace("PrimaryExpression: Number");
//
// Generate code for loading a numeric literal.
// This symbol lives in instruction memory.
//
setLine();
oSym = new CalcSymbol(value);
oSym.setStore(CalcSymbol.StorePerm);
$$ = generate(Instruction.gLoad);
generate((Object) oSym);
return $$;
}
| LOOKAHEAD(FunctionCall()) $$ = FunctionCall() {
yyTrace("PrimaryExpression: FunctionCall");
return $$;
}
| $$ = Accessor() {
yyTrace("PrimaryExpression: Accessor");
return $$;
}
| $$ = SimpleExpression() {
return $$;
}
}
double Number() : {
double $$;
Token $1;
}
{
(
$1 = {
yyTrace("Number: INTEGER");
}
| $1 = {
yyTrace("Number: REAL");
}
)
{
try {
$$ = Double.parseDouble($1.image);
} catch (NumberFormatException e) {
$$ = Double.NaN;
}
}
{
return $$;
}
}
int FunctionCall() : {
int $$;
String $1;
int $2, $3, $4;
}
{
$1 = Identifier() {
setLine();
$2 = moCode.generate();
} $4 = Arguments() {
yyTrace("FunctionCall: Identifier ( ArgumentList )");
//
// Upcase the identifier, and
//
StringBuilder sFunction = new StringBuilder($1);
for (int i = 0; i < sFunction.length(); i++) {
char c = sFunction.charAt(i);
if ('a' <= c && c <= 'z')
sFunction.setCharAt(i, (char) (c & ~0x20));
}
//
// Check if its the name of a builtin function.
//
CalcSymbol oFuncSym = mBuiltin.lookup(sFunction.toString());
//
// If not Then check if its the name of a user-defined function.
//
if (oFuncSym == null)
oFuncSym = moData.lookup($1);
//
// If neither Then error -- function unknown...
//
if (oFuncSym == null && ! mbInSyntaxCheckMode) {
yyError(ResId.FC_ERR_FUNC_UNKN, $1);
}
else {
//
// Generate code for calling a function.
//
generate(Instruction.gCall);
generate($1);
generate(Integer.valueOf($4));
}
return $2;
}
| $$ = If() $3 = Arguments() { // Javaport: try moving into IfExpression()
yyTrace("FunctionCall: If ( ArgumentList )");
setLine();
//
// Generate code for stoppage of this execution thread.
//
int nStopOffset = generate(Instruction.gStop);
//
// The IF keyword had caused us to previously generate code
// for an if instruction, and in front of all instructions for
// the argument list. However, this is the If builtin function,
// so instead of backfixing the addresses of the if instruction,
// supplant code for an iffunc instruction. It will take care
// of evaluating the argument list and invoking the if builtin
// function.
//
int nIf = moCode.getCodeStart() + $$;
moCode.moCodeBase[nIf + 0] = Instruction.gIfFunc;
moCode.moCodeBase[nIf + 1] = Integer.valueOf($3);
moCode.moCodeBase[nIf + 3] = Integer.valueOf(nStopOffset - $$ + 1); // endif part
return $$;
}
}
int Accessor() : {
int $$;
String $1, $3;
Method $2;
int $5;
CalcSymbol oSym;
}
{
$1 = Identifier() {
yyTrace("Accessor: Identifier");
oSym = null;
//
// Is identifier a formal parameter?
//
if (mbInFuncDeclaration)
oSym = moData.lookup((msFunc + $1));
//
// No. Is identifier a variable?
//
if (oSym == null)
oSym = moData.lookup($1, moScope);
//
// No. Then identifier an accessor!
//
if (oSym == null) {
oSym = new CalcSymbol();
oSym.setName($1);
oSym.setType(CalcSymbol.TypeAccessor);
oSym.setStore(CalcSymbol.StorePerm);
}
//
// Generate code for loading of a formal parameter,
// variable or accesssor.
// Note: this symbol lives in instruction memory.
//
$$ = generate(Instruction.gLoad);
generate(oSym);
}
(
(
LOOKAHEAD(DotOp() Identifier() Arguments()) $2 = DotOp() $3 = Identifier() $5 = Arguments() {
yyTrace("Accessor: Accessor DotOp Identifier ( ArgumentList )");
//
// Generate code for a method call instruction.
//
generate(Instruction.gForm);
generate($3);
generate(Integer.valueOf($5));
//
// Generate code for dot operator instruction.
//
$$ = generate($2);
}
| $2 = DotOp() $3 = Identifier() {
yyTrace("Accessor: Accessor DotOp Identifier");
//
// Generate accessor symbol from right hand identifier.
//
oSym = new CalcSymbol();
oSym.setName($3);
oSym.setType(CalcSymbol.TypeAccessor);
oSym.setStore(CalcSymbol.StorePerm);
//
// Generate code for loading of identifier.
//
generate(Instruction.gLoad);
generate(oSym);
//
// Generate code for dot operator instruction.
//
$$ = generate($2);
}
| {
yyTrace("Accessor: Accessor .* ");
$$ = generate(Instruction.gDotstar);
}
|
(
{
yyTrace("Accessor: Accessor [ * ]");
//
// Generate accessor symbol who's name is '*'.
//
oSym = new CalcSymbol();
oSym.setName("*");
oSym.setType(CalcSymbol.TypeAccessor);
oSym.setStore(CalcSymbol.StorePerm);
//
// Generate code for loading of accessor.
//
generate(Instruction.gLoad);
generate(oSym);
//
// Generate code for indexing instruction.
//
$$ = generate(Instruction.gIndex);
}
| SimpleExpression() {
yyTrace("Accessor: Accessor [ SimpleExpression ]");
$$ = generate(Instruction.gIndex);
}
)
)
)* {
return $$;
}
}
Method DotOp() : {
Method $$;
}
{
(
{
$$ = Instruction.gDotdot;
}
| {
$$ = Instruction.gDothash;
}
| {
$$ = Instruction.gDot;
}
) {
return $$;
}
}
String Identifier() : {
Token $1;
}
{
( $1 = | $1 = ) {
return $1.image;
}
}
void Or() : {
}
{
|
}
void And() : {
}
{
|
}
void Eq() : {
}
{
|
}
void Ne() : {
}
{
|
}
void Le() : {
}
{
|
}
void Lt() : {
}
{
|
}
void Ge() : {
}
{
|
}
void Gt() : {
}
{
|
}
void Null() : {
}
{
|
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy