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 }