View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  package org.millscript.millscript.syntax;
23  
24  import org.millscript.millscript.alert.Alerts;
25  import org.millscript.millscript.expr.Expr;
26  import org.millscript.millscript.expr.If2Expr;
27  import org.millscript.millscript.expr.If3Expr;
28  import org.millscript.millscript.expr.NotExpr;
29  
30  /**
31   * This class implements conditional(<code>if</code>/<code>unless</code>)
32   * syntax.
33   *
34   * @see If2Expr
35   * @see If3Expr
36   * @see NotExpr
37   */
38  public final class ConditionalSyntax extends PrefixSyntax {
39  
40      /**
41       * The closing character sequence for this instance of conditional syntax.
42       */
43      private final String closer;
44  
45      /**
46       * Creates a conditional syntax parser instance, with the specified closing
47       * character sequence.
48       *
49       * @param   s   the closing character sequence for this condition syntax
50       *              parser instance
51       */
52      ConditionalSyntax( final String s ) {
53          closer = s.intern();
54      }
55  
56      /**
57       * @see org.millscript.millscript.syntax.PrefixSyntaxInterface#prefix(java.lang.String, org.millscript.millscript.syntax.Parser)
58       */
59      @Override
60      public Expr prefix( final String sym, final Parser parser ) {
61          // Read the condition
62          Expr pred = parser.readExprTo( "then" );
63          // Check if we're parsing an unless statement
64          if ( sym == "unless" ) {
65              // We're parsing an unless statement, so we wrap the first condition
66              // in a not expression to invert it.
67              pred = NotExpr.make( pred );
68          }
69          // Now read the block to be executed if the condition is true
70          Expr ifso = parser.readBlock();
71          // Now continue to read the remainder of the conditional statement.
72          if ( parser.tryRead( closer ) ) {
73              // We've read the last condition and it's associated block, so we
74              // can use this slightly simpler expression for this case
75              return new If2Expr( pred, ifso );
76          } else if ( parser.tryRead( "else" ) ) {
77              // There is an else block for this conditional statement, so we read
78              // the block of code.
79              Expr ifnot = parser.readBlockTo( closer );
80              // And then return an expression for the thing-else-endthing block
81              return If3Expr.make( pred, ifso, ifnot );
82          } else if ( parser.tryRead( "elseif" ) ) {
83              // There is an elseif block, so we recursively read this as a new if
84              // statement
85              Expr ifnot = this.prefix( "if", parser );
86              // and then return an expression for the thing-elseif-otherthing
87              // block
88              return If3Expr.make( pred, ifso, ifnot );
89          } else if ( parser.tryRead( "elseunless" ) ) {
90              // There is an elseunless block, so we recursively read this as a
91              // new unless statement
92              Expr ifnot = this.prefix( "unless", parser );
93              // and then return an expression for the thing-elseunless-otherthing
94              // block
95              return If3Expr.make( pred, ifso, ifnot );
96          } else {
97              // unexpected token in conditional statement
98              throw(
99                  Alerts.parse(
100                     "Unexpected token",
101                     "Wanted else/endif/endunless/elseif/elseunless"
102                 ).culprit( "token", parser.getErrorString() ).mishap()
103             );
104         }
105     }
106 
107 }