OLD | NEW |
| (Empty) |
1 part of smalltalk; | |
2 | |
3 /** | |
4 * Smalltalk grammar. | |
5 */ | |
6 class SmalltalkGrammar extends GrammarParser { | |
7 SmalltalkGrammar() : super(new SmalltalkGrammarDefinition()); | |
8 } | |
9 | |
10 /** | |
11 * Smalltalk grammar definition. | |
12 */ | |
13 class SmalltalkGrammarDefinition extends GrammarDefinition { | |
14 | |
15 // the original implementation used a handwritten parser to | |
16 // build special token objects | |
17 token(input) { | |
18 if (input is String) { | |
19 input = input.length == 1 ? char(input) : string(input); | |
20 } | |
21 return input.token().trim(ref(spacer)); | |
22 } | |
23 | |
24 // the original implementation uses a handwritten parser to | |
25 // efficiently consume whitespace and comments | |
26 spacer() => whitespace() | |
27 .or(ref(comment)); | |
28 comment() => char('"') | |
29 .seq(char('"').neg().star()) | |
30 .seq(char('"')); | |
31 | |
32 // the original implementation uses the hand written number | |
33 // parser of the system, this is the spec of the ANSI standard | |
34 number() => char('-').optional() | |
35 .seq(ref(positiveNumber)); | |
36 positiveNumber() => ref(scaledDecimal) | |
37 .or(ref(float)) | |
38 .or(ref(integer)); | |
39 | |
40 integer() => ref(radixInteger) | |
41 .or(ref(decimalInteger)); | |
42 decimalInteger() => ref(digits); | |
43 digits() => digit().plus(); | |
44 radixInteger() => ref(radixSpecifier) | |
45 .seq(char('r')) | |
46 .seq(ref(radixDigits)); | |
47 radixSpecifier() => ref(digits); | |
48 radixDigits() => pattern('0-9A-Z').plus(); | |
49 | |
50 float() => ref(mantissa) | |
51 .seq(ref(exponentLetter) | |
52 .seq(ref(exponent)) | |
53 .optional()); | |
54 mantissa() => ref(digits) | |
55 .seq(char('.')) | |
56 .seq(ref(digits)); | |
57 exponent() => char('-') | |
58 .seq(ref(decimalInteger)); | |
59 exponentLetter() => pattern('edq'); | |
60 | |
61 scaledDecimal() => ref(scaledMantissa) | |
62 .seq(char('s')) | |
63 .seq(ref(fractionalDigits).optional()); | |
64 scaledMantissa() => ref(decimalInteger) | |
65 .or(ref(mantissa)); | |
66 fractionalDigits() => ref(decimalInteger); | |
67 | |
68 // the original smalltalk grammar | |
69 array() => ref(token, '{') | |
70 .seq(ref(expression).separatedBy(ref(periodToken)) | |
71 .seq(ref(periodToken).optional()).optional()) | |
72 .seq(ref(token, '}')); | |
73 arrayItem() => ref(literal) | |
74 .or(ref(symbolLiteralArray)) | |
75 .or(ref(arrayLiteralArray)) | |
76 .or(ref(byteLiteralArray)); | |
77 arrayLiteral() => ref(token, '#(') | |
78 .seq(ref(arrayItem).star()) | |
79 .seq(ref(token, ')')); | |
80 arrayLiteralArray() => ref(token, '(') | |
81 .seq(ref(arrayItem).star()) | |
82 .seq(ref(token, ')')); | |
83 assignment() => ref(variable) | |
84 .seq(ref(assignmentToken)); | |
85 assignmentToken() => ref(token, ':='); | |
86 binary() => pattern('!%&*+,-/<=>?@\\|~').plus(); | |
87 binaryExpression() => ref(unaryExpression) | |
88 .seq(ref(binaryMessage).star()); | |
89 binaryMessage() => ref(binaryToken) | |
90 .seq(ref(unaryExpression)); | |
91 binaryMethod() => ref(binaryToken) | |
92 .seq(ref(variable)); | |
93 binaryPragma() => ref(binaryToken) | |
94 .seq(ref(arrayItem)); | |
95 binaryToken() => ref(token, ref(binary)); | |
96 block() => ref(token, '[') | |
97 .seq(ref(blockBody)) | |
98 .seq(ref(token, ']')); | |
99 blockArgument() => ref(token, ':') | |
100 .seq(ref(variable)); | |
101 blockArguments() => ref(blockArgumentsWith) | |
102 .or(ref(blockArgumentsWithout)); | |
103 blockArgumentsWith() => ref(blockArgument).plus() | |
104 .seq(ref(token, '|').or(ref(token, ']').and())); | |
105 blockArgumentsWithout() => epsilon(); | |
106 blockBody() => ref(blockArguments) | |
107 .seq(ref(sequence)); | |
108 byteLiteral() => ref(token, '#[') | |
109 .seq(ref(numberLiteral).star()) | |
110 .seq(ref(token, ']')); | |
111 byteLiteralArray() => ref(token, '[') | |
112 .seq(ref(numberLiteral).star()) | |
113 .seq(ref(token, ']')); | |
114 cascadeExpression() => ref(keywordExpression) | |
115 .seq(ref(cascadeMessage).star()); | |
116 cascadeMessage() => ref(token, ';') | |
117 .seq(ref(message)); | |
118 character() => char('\$').seq(any()); | |
119 characterLiteral() => ref(characterToken); | |
120 characterToken() => ref(token, ref(character)); | |
121 expression() => ref(assignment).star() | |
122 .seq(ref(cascadeExpression)); | |
123 falseLiteral() => ref(falseToken); | |
124 falseToken() => ref(token, 'false') | |
125 .seq(word().not()); | |
126 identifier() => pattern('a-zA-Z_') | |
127 .seq(word().star()); | |
128 identifierToken() => ref(token, ref(identifier)); | |
129 keyword() => ref(identifier) | |
130 .seq(char(':')); | |
131 keywordExpression() => ref(binaryExpression) | |
132 .seq(ref(keywordMessage).optional()); | |
133 keywordMessage() => ref(keywordToken) | |
134 .seq(ref(binaryExpression)).plus(); | |
135 keywordMethod() => ref(keywordToken) | |
136 .seq(ref(variable)).plus(); | |
137 keywordPragma() => ref(keywordToken) | |
138 .seq(ref(arrayItem)).plus(); | |
139 keywordToken() => ref(token, ref(keyword)); | |
140 literal() => ref(numberLiteral) | |
141 .or(ref(stringLiteral)) | |
142 .or(ref(characterLiteral)) | |
143 .or(ref(arrayLiteral)) | |
144 .or(ref(byteLiteral)) | |
145 .or(ref(symbolLiteral)) | |
146 .or(ref(nilLiteral)) | |
147 .or(ref(trueLiteral)) | |
148 .or(ref(falseLiteral)); | |
149 message() => ref(keywordMessage) | |
150 .or(ref(binaryMessage)) | |
151 .or(ref(unaryMessage)); | |
152 method() => ref(methodDeclaration) | |
153 .seq(ref(methodSequence)); | |
154 methodDeclaration() => ref(keywordMethod) | |
155 .or(ref(unaryMethod)) | |
156 .or(ref(binaryMethod)); | |
157 methodSequence() => ref(periodToken).star() | |
158 .seq(ref(pragmas)) | |
159 .seq(ref(periodToken).star()) | |
160 .seq(ref(temporaries)) | |
161 .seq(ref(periodToken).star()) | |
162 .seq(ref(pragmas)) | |
163 .seq(ref(periodToken).star()) | |
164 .seq(ref(statements)); | |
165 multiword() => ref(keyword).plus(); | |
166 nilLiteral() => ref(nilToken); | |
167 nilToken() => ref(token, 'nil') | |
168 .seq(word().not()); | |
169 numberLiteral() => ref(numberToken); | |
170 numberToken() => ref(token, ref(number)); | |
171 parens() => ref(token, '(') | |
172 .seq(ref(expression)) | |
173 .seq(ref(token, ')')); | |
174 period() => char('.'); | |
175 periodToken() => ref(token, ref(period)); | |
176 pragma() => ref(token, '<') | |
177 .seq(ref(pragmaMessage)) | |
178 .seq(ref(token, '>')); | |
179 pragmaMessage() => ref(keywordPragma) | |
180 .or(ref(unaryPragma)) | |
181 .or(ref(binaryPragma)); | |
182 pragmas() => ref(pragma).star(); | |
183 primary() => ref(literal) | |
184 .or(ref(variable)) | |
185 .or(ref(block)) | |
186 .or(ref(parens)) | |
187 .or(ref(array)); | |
188 answer() => ref(token, '^') | |
189 .seq(ref(expression)); | |
190 sequence() => ref(temporaries) | |
191 .seq(ref(periodToken).star()) | |
192 .seq(ref(statements)); | |
193 start() => ref(startMethod); | |
194 startMethod() => ref(method).end(); | |
195 statements() => ref(expression) | |
196 .seq(ref(periodToken).plus().seq(ref(statements)) | |
197 .or(ref(periodToken).star())) | |
198 .or(ref(answer).seq(ref(periodToken).star())) | |
199 .or(ref(periodToken).star()); | |
200 string_() => char('\'') | |
201 .seq(string('\'\'').or(pattern('^\'')).star()) | |
202 .seq(char('\'')); | |
203 stringLiteral() => ref(stringToken); | |
204 stringToken() => ref(token, ref(string_)); | |
205 symbol() => ref(unary) | |
206 .or(ref(binary)) | |
207 .or(ref(multiword)) | |
208 .or(ref(string_)); | |
209 symbolLiteral() => ref(token, '#').plus() | |
210 .seq(ref(token, ref(symbol))); | |
211 symbolLiteralArray() => ref(token, ref(symbol)); | |
212 temporaries() => ref(token, '|') | |
213 .seq(ref(variable).star()) | |
214 .seq(ref(token, '|')) | |
215 .optional(); | |
216 trueLiteral() => ref(trueToken); | |
217 trueToken() => ref(token, 'true') | |
218 .seq(word().not()); | |
219 unary() => ref(identifier) | |
220 .seq(char(':').not()); | |
221 unaryExpression() => ref(primary) | |
222 .seq(ref(unaryMessage).star()); | |
223 unaryMessage() => ref(unaryToken); | |
224 unaryMethod() => ref(identifierToken); | |
225 unaryPragma() => ref(identifierToken); | |
226 unaryToken() => ref(token, ref(unary)); | |
227 variable() => ref(identifierToken); | |
228 | |
229 } | |
OLD | NEW |