Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/metacosm/framework/parser/Parser.java


1   /*
2       Metacosm, an object-oriented network game framework
3       Copyright (C) 1999-2001 Metacosm Development Team
4   
5       This program is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published by
7       the Free Software Foundation; either version 2 of the License, or
8       (at your option) any later version.
9   
10      This program is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13      GNU General Public License for more details.
14  
15      You should have received a copy of the GNU General Public License
16      along with this program; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19  
20  package org.metacosm.framework.parser;
21  
22  import org.metacosm.framework.command.PlayerCommand;
23  import org.metacosm.framework.command.ControllerCommand;
24  import org.metacosm.framework.server.Configuration;
25  import org.metacosm.framework.server.Player;
26  import java.util.ArrayList;
27  import java.util.StringTokenizer;
28  
29  /**
30    * The Parser is used to parse (!) input streams from players.
31    * It's also a Singleton OOD pattern.
32    * 
33    * The following grammar is accepted:
34    * <verb>
35    * input::= pseudocmd ([;] pseudocmd)*
36    * pseudocmd::= (white)* command (white)*
37    * white::= [space]
38    * command::= cmdname (pseudoparam)* | (white)*
39    * pseudoparam::= white (white)* param
40    * param ::= [alphanum] ([alphanum])* | ['] [alphanum] ([alphanum])* [']
41    *
42    * Terminal symbol: [space] (space), [;] (commands delimiter), ['] (string delimiter], [alphanum] (others autorized characters)
43    * </verb>
44    */
45  final public class Parser {
46    // Class methods
47    /**
48     * @return the unique instance of the class.
49     */
50    public static Parser getInstance() {
51      if (parser == null) {
52        parser = new Parser();
53      }
54      return parser;
55    }
56  
57    /**
58      * Parses and executes the first command found in a string.
59      * An exception is thrown if something goes wrong.
60      * @return the end of the string
61      */
62    public String parse(Player player, String input) {
63      if (player == null || input == null) {
64        throw new java.lang.IllegalArgumentException();
65      }
66      String cmdName = null;
67      boolean playerCmd = false;
68  
69      // TODO RUFFY is it an alias?
70  
71      StringTokenizer st = new StringTokenizer(input,delimiters,true);
72      String part = junkWhites( st);
73  
74      // Find cmdName
75      if (part != null && !part.equals(" ")) {
76        if (part.equals(str_delim) || part.equals(cmd_delim)) {
77          throw new ExpectedCommandException();
78        } else {
79          cmdName = new String(part);
80        }  
81      } else {
82        // no command
83        return null;
84      }
85  
86      playerCmd = isPlayerCommand( cmdName);
87  
88      // Parameters or not?
89      ArrayList params = new ArrayList();
90      if (st.hasMoreTokens() && ! (part = st.nextToken()).equals(cmd_delim)) {
91        // Should find a white or a command delimiter
92        if (! part.equals(" ")) {
93          throw new UnexpectedStringException();
94        }
95  
96        part = junkWhites( st);
97  
98        // Find parameters
99        String param = null;
100       boolean endParam = (part==null);
101       while (! endParam) {
102         if (part.equals(str_delim)) {
103           if (param != null) {
104             // string in the middle of the param;
105             throw new UnexpectedStringException();
106           }
107           param = new String(str_delim);
108           part = null;
109           // find next string delimiter
110           while (st.hasMoreTokens() && !(part = st.nextToken()).equals(str_delim)) {
111             param += part;
112           }
113           if (part != null && param.equals(str_delim)) {
114             throw new EmptyStringException();
115           } else if ( part == null || !part.equals(str_delim)) {
116             throw new UnfinishedStringException();
117           } else  {
118             if (st.hasMoreTokens()) {
119               part = st.nextToken();
120               if (part.equals(str_delim)) {
121                 throw new UnexpectedStringException();
122               } else if (!part.equals(cmd_delim) && !part.equals(" ")) {
123                 throw new InvalidParameterException();
124               } else if (part.equals(cmd_delim)) {
125                 endParam = true;
126               }
127             }
128             // removes the first character (str_delim)
129             params.add(param.substring(1)); 
130             param = null;
131           }
132         } else if (part.equals(cmd_delim)) {
133           endParam = true;
134           if (param != null) {
135             params.add(param);
136             param = null;
137           }
138         } else if (part.equals(" ")) {
139           if (param != null) {
140             params.add(param);
141             param = null;
142           }
143         } else {
144           param = new String(part);
145         }
146         if (st.hasMoreTokens() && !endParam) {
147           part = st.nextToken();
148         } else {
149           endParam = true;
150           if (param != null) {
151             params.add(param);
152           }
153         }
154       }
155     }
156 
157     // Execute command(cmdName, params)
158     // TODO RUFFY log all cmds
159     if (playerCmd) {
160       PlayerCommand pc = CommandsManager.getInstance().getPlayerCommand(cmdName);
161       player.execute(pc, params);
162     } else {
163       ControllerCommand cc = CommandsManager.getInstance().getControllerCommand(cmdName);
164       player.execute(cc, params);
165     }
166 
167     // Return rest of input string
168     try {
169       part = st.nextToken("");
170     } catch( java.util.NoSuchElementException e) {
171       part = null; 
172     }
173 
174     return part;
175   }
176 
177   /**
178    * Junks leading whites.
179    */
180   private String junkWhites( StringTokenizer st) {
181     boolean ok = true;
182     String part = null;
183     while (st.hasMoreTokens() && ok) {
184       part = st.nextToken();
185       ok = part.equals(" ");
186     }
187     return part;
188   }
189 
190   /**
191    * Tests if a command is a PlayerCommand or a ControllerCommand.
192    * Throws exception in other cases.
193    */
194   boolean isPlayerCommand( String cmdName) {
195     if (CommandsManager.getInstance().containsPlayerCommand(cmdName))  {
196       return true;
197     } else if (CommandsManager.getInstance().containsControllerCommand(cmdName)) {
198       return false;
199     } else {
200       throw new UnknownCommandException();
201     }
202   }
203 
204   /**
205    * The constructor is private because of singleton pattern.
206    * Sets the command and string delimiters from configuration file.
207    * Throws exceptions if incorrect delimiters.
208    */
209   private Parser() {
210     Configuration configuration = Configuration.getInstance();
211     cmd_delim = configuration.getString(Configuration.PARSER_COMMANDS_DELIMITER);
212     str_delim = configuration.getString(Configuration.PARSER_STRING_DELIMITER);
213     if (cmd_delim.equals(" ")) {
214       System.out.println(configuration.getString(Configuration.PARSER_BAD_COMMAND_DELIMITER));
215       throw new BadCommandDelimiterException();
216     } else if (str_delim.equals( " ")) {
217       System.out.println(configuration.getString(Configuration.PARSER_BAD_STRING_DELIMITER));
218       throw new BadStringDelimiterException();
219     } else if (cmd_delim.equals(str_delim)) {
220       System.out.println(configuration.getString(Configuration.PARSER_BAD_STRING_AND_COMMAND_DELIMITERS));
221       throw new BadStringAndCommandDelimitersException();
222     } else {
223       delimiters = " " + cmd_delim + str_delim;
224     }
225   }
226 
227   /**
228    * The instance of the class. 
229    */
230   private static Parser parser;
231 
232   /**
233    * Characters used to separe tokens
234    * Default is space, <i>cmd_delim</i> and <i>str_delim</i>.
235    * @see cmd_delim
236    * @see str_delim
237    */
238   private static String delimiters;
239 
240   /**
241    * Character used to delimit a string
242    */
243   private static String str_delim;
244 
245   /**
246    * Character used to separe commands
247    */
248   private static String cmd_delim;
249 }