/* Protocol Definition Language Copyright (C) 2003-2006 Marcus Andersson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package net.sf.nmedit.jpdl2.utils; import java.util.Iterator; import net.sf.nmedit.jpdl2.dom.PDLBlock; import net.sf.nmedit.jpdl2.dom.PDLCaseStatement; import net.sf.nmedit.jpdl2.dom.PDLChoice; import net.sf.nmedit.jpdl2.dom.PDLConditional; import net.sf.nmedit.jpdl2.dom.PDLConstant; import net.sf.nmedit.jpdl2.dom.PDLDocument; import net.sf.nmedit.jpdl2.dom.PDLInstruction; import net.sf.nmedit.jpdl2.dom.PDLItem; import net.sf.nmedit.jpdl2.dom.PDLItemType; import net.sf.nmedit.jpdl2.dom.PDLMultiplicity; import net.sf.nmedit.jpdl2.dom.PDLOptional; import net.sf.nmedit.jpdl2.dom.PDLPacketDecl; import net.sf.nmedit.jpdl2.dom.PDLPacketRef; import net.sf.nmedit.jpdl2.dom.PDLSwitchStatement; import net.sf.nmedit.jpdl2.dom.PDLVariable; /** * TODO */ public class PDLWriter { private int indentIncrement = 4; private String newline = "\r\n"; private StringBuilder s; private String headerComment = "# generated by "+getClass().getName(); private boolean printHeaderComment = true; public void setHeaderCommentEnabled(boolean enable) { this.printHeaderComment = enable; } public static String toString(PDLDocument doc) { StringBuilder s = new StringBuilder(); PDLWriter w = new PDLWriter(s); w.append(doc); return s.toString(); } public PDLWriter(StringBuilder s) { this.s = s; } public void append(PDLDocument doc) { if (headerComment != null && printHeaderComment) { s.append(headerComment); s.append(newline); } for (PDLPacketDecl packetdecl: doc) { append(packetdecl); s.append(newline); } } public void append(PDLOptional optional) { s.append('?'); appendBlock(optional, 0); } public void append(PDLMultiplicity multiplicity) { if (multiplicity.getConstant()>=0) { s.append(Integer.valueOf(multiplicity.getConstant())); s.append('*'); } else if (multiplicity.getVariable() != null) { s.append(multiplicity.getVariable()); s.append('*'); } } public void append(PDLConstant constant) { if (constant.getMultiplicity() != null) append(constant.getMultiplicity()); s.append(Integer.valueOf(constant.getValue())); s.append(':'); s.append(Integer.valueOf(constant.getSize())); } public void append(PDLVariable variable) { if (variable.getType() == PDLItemType.AnonymousVariable) s.append("%"); if (variable.getMultiplicity() != null) append(variable.getMultiplicity()); s.append(variable.getName()); s.append(':'); s.append(Integer.valueOf(variable.getSize())); if (variable.getFunction() != null) { s.append('='); s.append(variable.getFunction()); } } public void append(PDLPacketRef packetReference) { if (packetReference.getType() == PDLItemType.PacketRefList) append(packetReference.getMultiplicity()); s.append(packetReference.getPacketName()); s.append('$'); if (packetReference.getType() == PDLItemType.InlinePacketRef) s.append('$'); else s.append(packetReference.getBinding()); } public void append(PDLConditional conditionalBlock) { append(conditionalBlock, 0); } public void append(PDLConditional conditionalBlock, int indent) { s.append(conditionalBlock.getCondition()); s.append(' '); appendBlock(conditionalBlock, indent+indentIncrement); } private void appendBlock(PDLBlock block, int indent) { if (block.getItemCount() == 1) { append(block.getItem(0)); s.append(newline); } else if (block.getItemCount() > 1) { if (!(block instanceof PDLPacketDecl)) s.append("{"); s.append(newline); for (int i=0;i<block.getItemCount();i++) { s.append(' '); append(' ', (i+1)%6==0 ? indent : 0); PDLItem item = block.getItem(i); append(item, indent); } s.append(newline); if (!(block instanceof PDLPacketDecl)) s.append('}'); s.append(newline); } } public void append(PDLItem item) { append(item, 0); } public void append(PDLItem item, int indent) { switch (item.getType()) { case Conditional: append(item.asConditional(), indent+indentIncrement); break; case Constant: append(item.asConstant()); break; case InlinePacketRef: case PacketRef: case PacketRefList: append(item.asPacketRef()); break; case Variable: case VariableList: case ImplicitVariable: case AnonymousVariable: append(item.asVariable()); break; case Optional: append(item.asOptional()); break; case Choice: append(item.asChoice()); break; case SwitchStatement: append(item.asSwitchStatement()); break; case Fail: s.append("fail()"); break; case Block: append(item.asBlock()); break; case Label: s.append("@"+item.asInstruction().getString()); break; case MessageId: s.append("messageId(\""+item.asInstruction().getString()+"\") "); break; case StringDef: { PDLInstruction ins = item.asInstruction(); s.append(ins.getString()+":=\""+ins.getString2()+"\""); break; } default: throw new InternalError("unsupported type: "+item.getType()); } } private void append(PDLBlock block) { if (block.getItemCount()==1) { append(block.getItem(0)); return; } s.append('{'); for (PDLItem item: block) { append(item); s.append(' '); } s.append('}'); } private void append(PDLSwitchStatement sw) { s.append("switch ("+sw.getFunction()+")\n{\n"); for (PDLCaseStatement cs: sw) { if (cs.isDefaultCase()) s.append("default:"); else s.append("case "+cs.getValue()+":"); append(cs.getBlock()); } s.append("}\n"); } private void append(PDLChoice m) { s.append('('); Iterator<PDLBlock> b = m.iterator(); if (b.hasNext()) { append(b.next()); while (b.hasNext()) { s.append('|'); append(b.next()); } } s.append(')'); } public void append(PDLPacketDecl pdecl) { s.append(pdecl.getName()); if (pdecl.getPadding()>1) { s.append('%'); s.append(Integer.valueOf(pdecl.getPadding())); } s.append(" := \r\n"); appendBlock(pdecl, 0); s.append("\r\n"); append(' ', indentIncrement); s.append(";\r\n"); } private void append(char c, int count) { while (count>0) { s.append(c); count--; } } }