//-------------------------------------------------------------------------------------------------- // // @ CopyRight Roberti & Parau Enterprises, Inc. 2021-2023 // // This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/ // or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. // //-------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ // // Javacc parser use to parse macro's header line // //------------------------------------------------------------------------------ options { STATIC=false; SUPPORT_CLASS_VISIBILITY_PUBLIC= true; FORCE_LA_CHECK= true; LOOKAHEAD= 1; DEBUG_TOKEN_MANAGER= false; } PARSER_BEGIN(DVMacroHeaderParser) package framework; import java.util.LinkedList; import java.util.ArrayList; import java.util.HashMap; import javax.script.ScriptException; public class DVMacroHeaderParser { private String getState() { return DVMacroHeaderParserTokenManager.lexStateNames[token_source.curLexState]; } DVMacros.Macro macro; LinkedList nestStack= new LinkedList(); } PARSER_END(DVMacroHeaderParser) // // Token manager declarations // TOKEN_MGR_DECLS : { protected int nestCount= 0; } // // Tokens // SKIP : { < (("/>") ((~["\n"])*) ("\n//") ([" ","\t"])*)> } TOKEN : { } TOKEN : { } TOKEN [IGNORE_CASE] : { | : PARM_STATE } TOKEN [IGNORE_CASE] : { | | } TOKEN : { | | | ("]")> | (("-")?) ("]")> | | <#LISTN: (["1"-"9"]) ((["0"-"9"])?)> } TOKEN [IGNORE_CASE] : { } TOKEN : { | | | | | { this.nestCount++; } | { this.nestCount--; } | { this.nestCount++; } | { this.nestCount--; } | { this.nestCount++; } | { this.nestCount--; } | { if (this.nestCount <= 0) SwitchTo(PARM_STATE); } | } TOKEN : { } // // Start grammar here // void start(DVMacros.Macro macro) throws ScriptException: { this.macro= macro; Token t; } { ( t= { if (! this.macro.macroName.equalsIgnoreCase(t.image)) error("Header macro name [%s] does not match external macro name [%s]", t.image, macro.macroName); getParm(); if (macro.minPosParmSize == null) macro.minPosParmSize= macro.posParm.size(); return; } ) } void getParm() throws ScriptException: { Token t; String nameList= ""; int x= 0; DVMacroParm parm= null; } { ( ( ) ? ( t= { if (macro.minPosParmSize == null) { macro.minPosParmSize= macro.posParm.size(); getParm(); return; } error("Dupliate optional directive at position [%d]", t.beginColumn); } | t= { if (t.image.equals("Label")) error("Parameter name [Label] encountered in position[%d] is reserved and cannot be used", t.beginColumn); if (nameList.indexOf(" " + t.image + " ") >= 0) error("Duplicate parameter name [%s] at position [%d]", t.image, t.beginColumn); nameList+= " " + t.image + " "; parm= new DVMacroParm(t.image); } | { return; } ) ( { parm.isInt= true; } | { parm.isBool= true; } ) ? ( t= { parm.isList= true; } | t= { parm.isList= true; parm.minListSize= Integer.valueOf(t.image.substring(1, t.image.length()-1)); } | t= { parm.isList= true; x= t.image.indexOf('-'); parm.minListSize= Integer.valueOf(t.image.substring(1, x)); parm.maxListSize= Integer.valueOf(t.image.substring(x+1, t.image.length()-1)); } ) ? ( { parm.isKeyWord= true; macro.keyParm.put(parm.name.toUpperCase(), parm); parm.defaultValue= parm.name + "="; if (parm.isList) getValueList(parm); else if (parm.isBool || parm.isInt) getValueType(parm); else getValueStr(parm); return; } ) ? ( ) ? ( { macro.posParm.add(parm); getParm(); return; } | { macro.posParm.add(parm); return; } ) ) } void getValueList(DVMacroParm parm) throws ScriptException: { Token t; } { ( ) ? ( ) { parm.defaultValue+= "["; if (parm.isBool || parm.isInt) getValueType(parm); else { this.nestStack.push('['); getValueStr(parm); } } } void getValueType(DVMacroParm parm) throws ScriptException: { Token t; int parmListNo= 0; } { ( ( ) ? // Clear leading spaces ( t= { if (! parm.isBool) processInvalid(t); String tmp= t.image.toLowerCase(); if (tmp.equals("yes")) parm.defaultValue+= "true"; else if (tmp.equals("no")) parm.defaultValue+= "false"; else parm.defaultValue+= tmp; } | t= { if (! parm.isInt) processInvalid(t); parm.defaultValue+= t.image; } ) ( ) ? ( t= { if (parm.isList) { parm.defaultValue+= "]"; parmListNo++; if (parm.minListSize != null) { if (parm.maxListSize != null && (parmListNo < parm.minListSize || parmListNo > parm.maxListSize)) error("List size [%d] for parameter [%s] in macro header is out of range - range is [%d-%d]", parmListNo, parm.name, parm.minListSize, parm.maxListSize); if (parm.maxListSize == null && parmListNo != parm.minListSize) error("List size [%d] for parameter [%s] in macro header is incorrect - correct size is [%d]", parmListNo, parm.name, parm.minListSize); } endList(parm); return; } processInvalid(t); } | { if (parm.isList) { parm.defaultValue+= ","; parmListNo++; } else { parm.defaultValue+= ";"; getParm(); return; } } | { if (parm.isList) error("End of header encountered with an uncompleted boolean/integer list"); parm.defaultValue+= ";"; return; } ) ) + } void getValueStr(DVMacroParm parm) throws ScriptException: { Token t; char c, d; int i; String value= ""; boolean expFlag= true; int parmListNo= 0; } { ( ( t= | t= | t= | t= ) { value+= t.image; } | ( t= | t= | t= ) { value+= t.image; this.nestStack.push(t.image.charAt(0)); } | ( t= | t= ) { value+= t.image; if (this.nestStack.isEmpty()) error("Extra bracket '%s' found at position %d", t.image, t.beginColumn); c= this.nestStack.pop(); d= t.image.charAt(0); if (! (c == '(' && d == ')' || c == '{' && d == '}')) error("Bracket mismatch - bracket '%c' at position [%d] does not match" + " bracket '%c'", d, t.beginColumn, c); } | ( t= | t= ) { value+= t.image.replace("\\", "\"") .replace("\\\"", "\"").replace("\\\'", "'"); } | t= { value+= t.image.substring(2, t.image.length()-1) .replace("\\", "\"").replace("\\\"", "\"").replace("\\\'", "'"); expFlag= false; } | t= { if (this.nestStack.isEmpty()) error("Unmatched square bracket ']' found at position[%d]", t.beginColumn); this.nestStack.pop(); if (parm.isList && this.nestStack.size() == 0) { if (expFlag) { String ts[]= DVUtil.expandList(value.strip().replace("\\", "\\\\") .replace("\"", "\\\"").replace("\'", "\\\'")); for (i= 0; i < ts.length-1; i++) parm.defaultValue+= "\"" + ts[i] + "\","; parm.defaultValue+= "\"" + ts[i] + "\"]"; parmListNo+= ts.length; } else { parm.defaultValue+= "\"" + value.strip().replace("\\", "\\\\") .replace("\"", "\\\"").replace("\'", "\\\'") + "\"]"; parmListNo++; } int l= parm.defaultValue.length(); if (parm.defaultValue.substring(l-4).equals("[\"\"]") && expFlag) { parm.defaultValue= parm.defaultValue.substring(0, l-4) + "[]"; parm.defaultValueEmpty= true; } else if (parm.minListSize != null) { if (parm.maxListSize != null && (parmListNo < parm.minListSize || parmListNo > parm.maxListSize)) error("List size [%d] for parameter [%s] in macro header is out of range - range is [%d-%d]", parmListNo, parm.name, parm.minListSize, parm.maxListSize); if (parm.maxListSize == null && parmListNo != parm.minListSize) error("List size [%d] for parameter [%s] in macro header is incorrect - correct size is [%d]", parmListNo, parm.name, parm.minListSize); } endList(parm); return; } value+= t.image; } | t= { if (this.nestStack.size() == 0 || (parm.isList && this.nestStack.size() == 1)) { if (expFlag) { String ts[]= DVUtil.expandList(value.strip().replace("\\", "\\\\") .replace("\"", "\\\"").replace("\'", "\\\'")); for (i= 0; i < ts.length-1; i++) parm.defaultValue+= "\"" + ts[i] + "\","; parm.defaultValue+= "\"" + ts[i] + "\""; parmListNo+= ts.length; } else { parm.defaultValue+= "\"" + value.strip().replace("\\", "\\\\") .replace("\"", "\\\"").replace("\'", "\\\'") + "\""; parmListNo++; } } if (this.nestStack.size() == 0) { parm.defaultValue+= ";"; getParm(); return; } parm.defaultValue+= ","; value= ""; } | { if (this.nestStack.size() > 0) error("Missing bracket '%s' at end of macro header", "0]}".charAt("([{".indexOf(this.nestStack.pop()))); parm.defaultValue+= "\"" + value.strip().replace("\\", "\\\\") .replace("\"", "\\\"").replace("\'", "\\\'") + "\";"; return; } ) + } void endList(DVMacroParm parm) throws ScriptException: { } { ( { parm.defaultValue+= ";"; getParm(); return; } | ) } void processInvalid(Token t) throws ScriptException: { } { { error(String.format("Invalid character '%s' found at position [%d]", t.image, t.beginColumn)); } } void error(String fmt, Object... args) throws ScriptException: {} { { if (macro.permError == null) macro.permError= String.format(fmt, args); throw new ScriptException(macro.permError); } }