📄 smccppgenerator.java
字号:
//// The contents of this file are subject to the Mozilla Public// License Version 1.1 (the "License"); you may not use this file// except in compliance with the License. You may obtain a copy// of the License at http://www.mozilla.org/MPL///// Software distributed under the License is distributed on an// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or// implied. See the License for the specific language governing// rights and limitations under the License.//// The Original Code is State Machine Compiler (SMC).//// The Initial Developer of the Original Code is Charles W. Rapp.// Portions created by Charles W. Rapp are// Copyright (C) 2005, 2006. Charles W. Rapp.// All Rights Reserved.//// Contributor(s):// Eitan Suez contributed examples/Ant.// (Name withheld) contributed the C# code generation and// examples/C#.// Francois Perrad contributed the Python code generation and// examples/Python.// Chris Liscio contributed the Objective-C code generation// and examples/ObjC.//// RCS ID// $Id: SmcCppGenerator.java,v 1.10 2008/03/21 14:03:16 fperrad Exp $//// CHANGE LOG// (See the bottom of this file.)//package net.sf.smc;import java.io.PrintStream;import java.util.Iterator;import java.util.List;import java.util.StringTokenizer;/** * Visits the abstract syntax tree emitting C++ code. * @see SmcElement * @see SmcCodeGenerator * @see SmcVisitor * * @author <a href="mailto:rapp@acm.org">Charles Rapp</a> */public final class SmcCppGenerator extends SmcCodeGenerator{//---------------------------------------------------------------// Member methods// public SmcCppGenerator(String srcfileBase) { super (srcfileBase, "{0}{1}_sm.{2}", "cpp"); } // end of SmcCppGenerator(String) // This method generates the following code: // // %{ %} raw source code - if any // // #include <%include header file> // #include "<context>_sm.h" // (If the -headerd option is used, then this is generated: // #include "<header dir>/<context>_sm.h") // // using namespace statemap; // using namespace <%import namespace> // // (put namespace a { namespace b ... if %package defined.) // // Static class declarations. // <map name>_<state name> <map name>::<state>("<map name>::<state name>", <index>) public void visit(SmcFSM fsm) { String srcDirectory = Smc.outputDirectory(); String headerDirectory = Smc.headerDirectory(); String packageName = fsm.getPackage(); String rawSource = fsm.getSource(); String context = fsm.getContext(); String mapName; List<SmcTransition> transList; String separator; List<SmcParameter> params; Iterator<SmcMap> mapIt; Iterator<SmcState> stateIt; String declaration; int packageDepth = 0; SmcMap map; SmcState state; int index; // Dump out the raw source code, if any. if (rawSource != null && rawSource.length() > 0) { _source.println(rawSource); _source.println(); } // Generate #includes. for (String include: fsm.getIncludes()) { _source.print("#include "); _source.println(include); } // Include the context file last. // Is the header file included in a different directory // than the source file? _source.print("#include \""); if ((srcDirectory == null && headerDirectory != null) || (srcDirectory != null && headerDirectory != null && srcDirectory.equals(headerDirectory) == false)) { // They are in different directories. Prepend the // header directory to the file name. _source.print(headerDirectory); } // Else they are in the same directory. else if (srcDirectory != null) { _source.print(srcDirectory); } _source.print(_srcfileBase); _source.println("_sm.h\""); // Import the statemap namespace symbols into the main // namespace. _source.println(); _source.println("using namespace statemap;"); // Do user-specified imports now. for (String imp: fsm.getImports()) { _source.print("using namespace "); _source.print(imp); _source.println(";"); } // End of namespace imports. _source.println(); // Import the user-defined namespace into the main // namespace. If the package name is "a::b::c", then // this must be converted to: // namespace a { // namespace b { // namespace c { // ... // } // } // } if (packageName != null && packageName.length() > 0) { _indent = ""; StringTokenizer tokenizer = new StringTokenizer(packageName, "::"); String token; while (tokenizer.hasMoreTokens() == true) { token = tokenizer.nextToken(); ++packageDepth; _source.print(_indent); _source.print("namespace "); _source.println(token); _source.print(_indent); _source.println("{"); _indent += " "; } } // Statically declare all derived state classes. _source.print(_indent); _source.println("// Static class declarations."); for (mapIt = fsm.getMaps().iterator(), index = 0; mapIt.hasNext() == true; ) { map = mapIt.next(); mapName = map.getName(); for (stateIt = map.getStates().iterator(); stateIt.hasNext() == true; ++index) { state = stateIt.next(); _source.print(_indent); _source.print(mapName); _source.print("_"); _source.print(state.getClassName()); _source.print(" "); _source.print(mapName); _source.print("::"); _source.print(state.getInstanceName()); _source.print("(\""); _source.print(mapName); _source.print("::"); _source.print(state.getClassName()); _source.print("\", "); _source.print(index); _source.println(");"); } } // v. 2.2.0: If supporting serialization, then set the // min and max indices and the state array. if (Smc.isSerial() == true) { _source.println(); _source.print(_indent); _source.print("const int "); _source.print(context); _source.println("Context::MIN_INDEX = 0;"); _source.print(_indent); _source.print("const int "); _source.print(context); _source.print("Context::MAX_INDEX = "); _source.print(--index); _source.println(";"); _source.print(_indent); _source.print(context); _source.print("State* "); _source.print(context); _source.println("Context::_States[] = "); _source.print("{"); for (mapIt = fsm.getMaps().iterator(), separator = ""; mapIt.hasNext() == true; ) { map = mapIt.next(); mapName = map.getName(); for (stateIt = map.getStates().iterator(); stateIt.hasNext() == true; separator = ",") { state = stateIt.next(); _source.print(separator); _source.println(); _source.print(_indent); _source.print(" &"); _source.print(mapName); _source.print("::"); _source.print(state.getClassName()); } } _source.println(); _source.print(_indent); _source.println("};"); } // If serialization is supported, then output the valueOf // method now. if (Smc.isSerial() == true) { _source.println(); _source.print(_indent); _source.print(context); _source.print("State& "); _source.print(context); _source.println("Context::valueOf(int stateId)"); _source.print(_indent); _source.println("{"); _source.print(_indent); _source.print(" if (stateId < MIN_INDEX || "); _source.println("stateId > MAX_INDEX)"); _source.print(_indent); _source.println(" {"); // If exceptions are not being thrown, then assert // instead. if (Smc.isNoExceptions() == true) { _source.print(_indent); _source.println(" assert(1==0);"); } else { _source.print(_indent); _source.println(" throw ("); _source.print(_indent); _source.println( " IndexOutOfBoundsException("); _source.print(_indent); _source.print( " stateId, MIN_INDEX, "); _source.println("MAX_INDEX));"); } _source.print(_indent); _source.println(" }"); _source.println(); _source.print(_indent); _source.print(" return (static_cast<"); _source.print(context); _source.print("State&>(*("); _source.println("_States[stateId])));"); _source.print(_indent); _source.println("}"); } // Print out the default definitions for all the // transitions. First, get the transitions list. transList = fsm.getTransitions(); // Output the default transition definitions. for (SmcTransition trans: transList) { if (trans.getName().equals("Default") == false) { _source.println(); _source.print(_indent); _source.print("void "); _source.print(context); _source.print("State::"); _source.print(trans.getName()); _source.print("("); _source.print(context); _source.print("Context& context"); params = trans.getParameters(); for (SmcParameter param: params) { _source.print(", "); param.accept(this); } _source.println(")"); _source.print(_indent); _source.println("{"); _source.print(_indent); _source.println(" Default(context);"); _source.print(_indent); _source.println(" return;"); _source.print(_indent); _source.println("}"); } } // Output the Default transition method ... almost. // If -g is being used, then add the "s" argname. _source.println(); _source.print(_indent); _source.print("void "); _source.print(context);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -