1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.millscript.syntax;
22
23 import org.millscript.commons.util.EList;
24 import org.millscript.commons.util.list.ELinkedList;
25 import org.millscript.millscript.alert.Alerts;
26 import org.millscript.millscript.expr.CommaExpr;
27 import org.millscript.millscript.expr.ConstantExpr;
28 import org.millscript.millscript.expr.Expr;
29 import org.millscript.millscript.expr.NameExpr;
30 import org.millscript.millscript.expr.SkipExpr;
31 import org.millscript.millscript.expr.SpiceClassExpr;
32 import org.millscript.millscript.expr.SpiceClassSlotExpr;
33 import org.millscript.millscript.expr.VarExpr;
34 import org.millscript.millscript.functions.SlotFunction;
35
36 /**
37 * This class implements <code>class</code> syntax.
38 *
39 * @see org.millscript.millscript.expr.SpiceClassExpr
40 * @see org.millscript.millscript.expr.VarExpr
41 */
42 public final class SpiceClassSyntax extends PrefixSyntax {
43
44 /**
45 * The closing character sequence for this instance of class syntax.
46 */
47 private final String closingKeyword;
48
49 /**
50 * The define syntax used for parsing method definitions.
51 */
52 private static final DefineSyntax DEFINE = new DefineSyntax();
53
54 /**
55 * Creates a class syntax parser instance, with the specified closing
56 * character sequence.
57 *
58 * @param x the closing character seqeunce for this class syntax parser
59 * instance
60 */
61 SpiceClassSyntax( final String x ) {
62 closingKeyword = x;
63 }
64
65 /**
66 * @see org.millscript.millscript.syntax.PrefixSyntaxInterface#prefix(java.lang.String, org.millscript.millscript.syntax.ParserImpl)
67 */
68 @Override
69 public Expr prefix( final String sym, final Parser parser ) {
70
71
72 Expr definitions = new SkipExpr();
73
74
75 Expr parentClasses = new SkipExpr();
76
77
78 final EList< SpiceClassSlotExpr > slotInitialisers = new ELinkedList< SpiceClassSlotExpr >();
79
80
81 final NameExpr className = parser.readName();
82
83
84 if ( parser.tryRead( "extends" ) ) {
85
86 parentClasses = CommaExpr.make( parentClasses, parser.readName() );
87 } else {
88 parentClasses = null;
89 }
90
91
92
93 final SpiceClassParserDelegate classParser = new SpiceClassParserDelegate( parser, className );
94
95
96 while ( !parser.tryRead( closingKeyword ) ) {
97 if ( parser.tryRead( "slot" ) ) {
98
99 final NameExpr slotName = parser.readName();
100
101
102 Expr slotValue = new ConstantExpr( null );
103
104 if ( parser.tryRead( "=" ) ) {
105
106 slotValue = parser.readExpr();
107 }
108 final SlotFunction sf = (SlotFunction) new SlotFunction().modName( slotName.getName() );
109
110 definitions = CommaExpr.make(
111 definitions,
112 new VarExpr(
113 false,
114 slotName,
115 new ConstantExpr( sf )
116 )
117 );
118
119 slotInitialisers.addLast(
120 new SpiceClassSlotExpr( sf, slotValue )
121 );
122 } else if ( parser.tryRead( "define" ) ) {
123
124
125 definitions = CommaExpr.make(
126 definitions,
127 DEFINE.prefix( "define", classParser )
128 );
129 } else {
130
131 throw(
132 Alerts.parse(
133 "Unexpected token in class definition",
134 "Only 'slot' is a valid token in a class body(at the moment)"
135 ).culprit( "token", parser.getErrorString() ).mishap()
136 );
137 }
138
139
140 parser.tryRead( ";" );
141 }
142
143
144 return CommaExpr.make(
145 new VarExpr(
146 false,
147 className,
148 new SpiceClassExpr( className.getName(), parentClasses, slotInitialisers )
149 ),
150 definitions
151 );
152 }
153
154 }