| 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 |