annotate modules/parser.tp @ 237:dae093baf36c

Optimized implementation of character classes
author Mike Pavone <pavone@retrodev.com>
date Sun, 05 Jan 2014 17:00:33 -0800
parents c463a891ccd3
children 6aab8a5a2be9
rev   line source
pavone@208 1 #{
pavone@209 2 _applyMatch <- :fun tomatch {
pavone@209 3 fun: tomatch
pavone@209 4 }
pavone@212 5 _matchString <- :str tomatch {
pavone@212 6 if: (tomatch isString?) {
pavone@212 7 if: (tomatch length) < (str length) {
pavone@212 8 #{
pavone@212 9 matched? <- { false }
pavone@212 10 }
pavone@212 11 } else: {
pavone@212 12 if: (tomatch length) > (str length) {
pavone@212 13 tomatch <- tomatch from: 0 withLength: (str length)
pavone@212 14 }
pavone@212 15 if: str = tomatch {
pavone@212 16 #{
pavone@212 17 matched? <- { true }
pavone@212 18 matchlen <- { str length }
pavone@213 19 basicYield? <- { true }
pavone@213 20 yield <- { str }
pavone@212 21 }
pavone@212 22 } else: {
pavone@212 23 #{
pavone@212 24 matched? <- { false }
pavone@212 25 }
pavone@212 26 }
pavone@212 27 }
pavone@212 28 } else: {
pavone@212 29 #{
pavone@212 30 matched? <- { false }
pavone@212 31 }
pavone@212 32 }
pavone@212 33 }
pavone@212 34 ifmatch:else <- :matchres :elseblock {
pavone@212 35 if: (matchres matched?) {
pavone@212 36 matchres
pavone@212 37 } else: {
pavone@212 38 elseblock:
pavone@212 39 }
pavone@212 40 }
pavone@212 41 _makeMatchCall <- :matchexpr {
pavone@212 42 if: (matchexpr nodeType) = "lambda" {
pavone@212 43 #{
pavone@212 44 valid? <- { true }
pavone@212 45 matchcall <- quote: (_applyMatch: matchexpr tomatch)
pavone@212 46 }
pavone@212 47 } else: {
pavone@212 48 if: (matchexpr nodeType) = "symbol" {
pavone@212 49 #{
pavone@212 50 valid? <- { true }
pavone@212 51 matchcall <- quote: (matchexpr: tomatch)
pavone@212 52 }
pavone@212 53 } else: {
pavone@212 54 if: (matchexpr nodeType) = "strlit" {
pavone@212 55 #{
pavone@212 56 valid? <- { true }
pavone@212 57 matchcall <- quote: (_matchString: matchexpr tomatch)
pavone@212 58 }
pavone@212 59 } else: {
pavone@212 60 if: (matchexpr nodeType) = "op" {
pavone@212 61 if: (matchexpr opName) = "." {
pavone@212 62 left <- (_makeMatchCall: (matchexpr left)) matchcall
pavone@212 63 right <- (_makeMatchCall: (matchexpr right)) matchcall
pavone@212 64 #{
pavone@212 65 valid? <- { true }
pavone@212 66 matchcall <- quote: (_applyMatch: :tomatch {
pavone@212 67 lm <- left
pavone@212 68 if: (lm matched?) {
pavone@220 69 orig <- tomatch
pavone@212 70 tomatch <- tomatch from: (lm matchlen)
pavone@212 71 rm <- right
pavone@212 72 if: (rm matched?) {
pavone@212 73 total <- (rm matchlen) + (lm matchlen)
pavone@212 74 #{
pavone@212 75 matched? <- { true }
pavone@212 76 matchlen <- { total }
pavone@213 77 basicYield? <- { true }
pavone@220 78 yield <- { orig from: 0 withLength: total }
pavone@212 79 }
pavone@212 80 } else: {
pavone@212 81 rm
pavone@212 82 }
pavone@212 83 } else: {
pavone@212 84 lm
pavone@212 85 }
pavone@212 86 } tomatch)
pavone@212 87 }
pavone@212 88 } else: {
pavone@212 89 #{
pavone@212 90 valid? <- { false }
pavone@212 91 message <- "Unsupported operator " . (matchexpr opName)
pavone@212 92 }
pavone@212 93 }
pavone@212 94 } else: {
pavone@212 95 #{
pavone@212 96 valid? <- { false }
pavone@212 97 message <- "Unsupported AST node type " . (matchexpr nodeType)
pavone@212 98 }
pavone@212 99 }
pavone@212 100 }
pavone@212 101 }
pavone@212 102 }
pavone@212 103 }
pavone@208 104 expandClass <- :chars {
pavone@208 105 if: (chars length) > 0 {
pavone@208 106 pos <- 0
pavone@208 107 inverted <- false
pavone@208 108 if: (chars byte: 0) = ("^" byte: 0) {
pavone@208 109 pos <- 1
pavone@208 110 inverted <- true
pavone@208 111 }
pavone@208 112 state_begin <- 0
pavone@208 113 state_normal <- 1
pavone@208 114 state_rangeend <- 2
pavone@208 115 state <- state_begin
pavone@208 116 out <- ""
pavone@208 117 while: { pos < (chars byte_length)} do: {
pavone@208 118 if: state = state_begin {
pavone@208 119 out <- out . (chars from: pos withLength: 1)
pavone@208 120 state <- state_normal
pavone@208 121 } else: {
pavone@208 122 if: state = state_normal {
pavone@208 123 if: (chars byte: pos) = ("-" byte: 0) {
pavone@208 124 state <- state_rangeend
pavone@208 125 } else: {
pavone@208 126 out <- out . (chars from: pos withLength: 1)
pavone@208 127 }
pavone@208 128 } else: {
pavone@208 129 rangestart <- out byte: ((out byte_length) - 1)
pavone@208 130 rangeend <- chars byte: pos
pavone@208 131 if: rangeend < rangestart {
pavone@208 132 tmp <- rangeend
pavone@208 133 rangeend <- rangestart
pavone@208 134 rangestart <- tmp
pavone@208 135 }
pavone@208 136 out <- out from: 0 withLength: ((out length) - 1)
pavone@208 137 while: { rangestart <= rangeend } do: {
pavone@208 138 out <- out . (rangestart asStringChar)
pavone@208 139 rangestart <- rangestart + 1
pavone@208 140 }
pavone@208 141 state <- state_begin
pavone@208 142 }
pavone@208 143 }
pavone@208 144 pos <- pos + 1
pavone@208 145 }
pavone@208 146 if: inverted {
pavone@208 147 old <- out
pavone@208 148 out <- ""
pavone@218 149 //skip control characters for now
pavone@218 150 cur <- 32
pavone@208 151 while: { cur < 256 } do: {
pavone@212 152 notfound <- true
pavone@212 153 idx <- 0
pavone@212 154 len <- (old length)
pavone@212 155 while: { notfound && idx < len } do: {
pavone@212 156 if: cur = (old byte: idx) {
pavone@212 157 notfound <- false
pavone@212 158 } else: {
pavone@212 159 idx <- idx + 1
pavone@212 160 }
pavone@212 161 }
pavone@212 162 if: notfound {
pavone@212 163 out <- out . (cur asStringChar)
pavone@212 164 }
pavone@208 165 cur <- cur + 1
pavone@208 166 }
pavone@208 167 }
pavone@208 168 out
pavone@208 169 } else: {
pavone@208 170 ""
pavone@208 171 }
pavone@208 172 }
pavone@208 173 charClass <- macro: :rawchars {
pavone@208 174 eval: rawchars :chars {
pavone@212 175 orig <- chars
pavone@208 176 chars <- expandClass: chars
pavone@237 177 charmap <- ""
pavone@237 178 char <- 0
pavone@237 179 while: { char < 256 } do: {
pavone@237 180 mchar <- 0
pavone@237 181 found <- false
pavone@237 182 while: { mchar < (chars byte_length)} do: {
pavone@237 183 if: (chars byte: mchar) = char {
pavone@237 184 found <- true
pavone@237 185 mchar <- chars byte_length
pavone@237 186 }
pavone@237 187 mchar <- mchar + 1
pavone@237 188 }
pavone@237 189 charmap <- charmap . (if: found { "t" } else: { "f" })
pavone@237 190 char <- char + 1
pavone@237 191 }
pavone@237 192 t <- "t" byte: 0
pavone@208 193 quote: :tomatch {
pavone@208 194 if: (tomatch isString?) {
pavone@237 195 if: (charmap byte: (tomatch byte: 0)) = t {
pavone@208 196 #{
pavone@208 197 matched? <- { true }
pavone@208 198 matchlen <- { 1 }
pavone@213 199 basicYield? <- { true }
pavone@213 200 yield <- { tomatch from: 0 withLength: 1 }
pavone@208 201 }
pavone@237 202 } else: {
pavone@237 203 #{
pavone@237 204 matched? <- { false }
pavone@237 205 }
pavone@208 206 }
pavone@208 207 } else: {
pavone@208 208 #{
pavone@208 209 matched? <- { false }
pavone@208 210 }
pavone@208 211 }
pavone@208 212 }
pavone@208 213 } else: {
pavone@212 214 print: "#error Argument to charClass macro must be a compile-time constant\n"
pavone@208 215 }
pavone@208 216 }
pavone@209 217
pavone@220 218 _nPlus <- :matchexpr min {
pavone@209 219 funexpr <- false
pavone@209 220 valid <- false
pavone@212 221 mc <- _makeMatchCall: matchexpr
pavone@212 222 if: (mc valid?) {
pavone@212 223 mcall <- mc matchcall
pavone@209 224 quote: :tomatch {
pavone@209 225 cur <- 0
pavone@220 226 count <- 0
pavone@209 227 n <- tomatch byte_length
pavone@209 228 orig <- tomatch
pavone@222 229 _match <- true
pavone@213 230 allBasic? <- true
pavone@213 231 yieldvals <- []
pavone@222 232 while: { _match && cur < n } do: {
pavone@212 233 res <- mcall
pavone@222 234 _match <- res matched?
pavone@222 235 if: _match {
pavone@220 236 count <- count + 1
pavone@209 237 //TODO: Use some kind of lightweight substring wrapper here
pavone@209 238 tomatch <- tomatch from: (res matchlen)
pavone@213 239 if: allBasic? {
pavone@213 240 ifnot: (res basicYield?) {
pavone@213 241 allBasic? <- false
pavone@218 242 if: cur > 0 {
pavone@218 243 yieldvals <- (orig from: 0 withLength: cur) | yieldvals
pavone@218 244 }
pavone@218 245 yieldvals <- (res yield) | yieldvals
pavone@213 246 }
pavone@213 247 } else: {
pavone@213 248 yieldvals <- (res yield) | yieldvals
pavone@213 249 }
pavone@213 250 allBasic? <- allBasic? && (res basicYield?)
pavone@209 251 cur <- cur + (res matchlen)
pavone@209 252 }
pavone@209 253 }
pavone@220 254 if: count >= min {
pavone@213 255 if: allBasic? {
pavone@213 256 #{
pavone@213 257 matched? <- { true }
pavone@213 258 matchlen <- { cur }
pavone@213 259 basicYield? <- { true }
pavone@213 260 yield <- { orig from: 0 withLength: cur }
pavone@213 261 }
pavone@213 262 } else: {
pavone@213 263 yieldvals <- yieldvals reverse
pavone@213 264 #{
pavone@213 265 matched? <- { true }
pavone@213 266 matchlen <- { cur }
pavone@213 267 basicYield? <- { false }
pavone@213 268 yield <- { yieldvals }
pavone@213 269 }
pavone@209 270 }
pavone@209 271 } else: {
pavone@209 272 #{
pavone@209 273 matched? <- { false }
pavone@209 274 }
pavone@209 275 }
pavone@209 276 }
pavone@209 277 } else: {
pavone@220 278 print: "#error Invalid nPlus macro call: " . (mc message) . "\n"
pavone@212 279 }
pavone@212 280 }
pavone@212 281
pavone@220 282 zeroPlus <- macro: :matchexpr {
pavone@220 283 _nPlus: matchexpr 0
pavone@220 284 }
pavone@220 285
pavone@220 286 onePlus <- macro: :matchexpr {
pavone@220 287 _nPlus: matchexpr 1
pavone@220 288 }
pavone@220 289
pavone@212 290 matchOne <- macro: :options {
pavone@212 291 options <- (options value) map: :option {
pavone@212 292 _makeMatchCall: option
pavone@212 293 }
pavone@212 294 body <- options foldr: (quote: #{
pavone@212 295 matched? <- { false }
pavone@212 296 }) with: :acc el {
pavone@212 297 if: (el valid?) {
pavone@212 298 mcall <- el matchcall
pavone@212 299 quote: (ifmatch: mcall else: { acc })
pavone@212 300 } else: {
pavone@212 301 print: "#error Invalid matchOne macro call: " . (el message) . "\n"
pavone@212 302 acc
pavone@212 303 }
pavone@212 304 }
pavone@212 305 quote: :tomatch {
pavone@212 306 body
pavone@209 307 }
pavone@209 308 }
pavone@209 309
pavone@222 310 match <- macro: :matchexpr {
pavone@222 311 mc <- _makeMatchCall: matchexpr
pavone@222 312 if: (mc valid?) {
pavone@222 313 mcall <- mc matchcall
pavone@222 314 quote: :tomatch {
pavone@222 315 mcall
pavone@222 316 }
pavone@222 317 } else: {
pavone@222 318 print: "#error Invalid macth macro call: " . (mc message) . "\n"
pavone@222 319 }
pavone@222 320 }
pavone@222 321
pavone@213 322 match:yield <- macro: :matchexpr :ylambda {
pavone@213 323 mc <- _makeMatchCall: matchexpr
pavone@213 324 if: (mc valid?) {
pavone@213 325 mcall <- mc matchcall
pavone@213 326 quote: :tomatch {
pavone@213 327 res <- mcall
pavone@213 328 if: (res matched?) {
pavone@213 329 #{
pavone@213 330 matched? <- { true }
pavone@213 331 matchlen <- { res matchlen }
pavone@213 332 basicYield? <- { false }
pavone@213 333 yield <- ylambda
pavone@213 334 }
pavone@213 335 } else: {
pavone@213 336 res
pavone@213 337 }
pavone@213 338 }
pavone@213 339 } else: {
pavone@213 340 print: "#error Invalid macth:yield macro call: " . (mc message) . "\n"
pavone@213 341 }
pavone@213 342 }
pavone@213 343
pavone@218 344 match:where:yield <- macro: :matchexpr :whereclause :ylambda {
pavone@218 345 syms <- []
pavone@218 346 withwhere <- (whereclause expressions) fold: (quote: :tomatch {}) with: :acc el {
pavone@218 347
pavone@218 348 if: (el nodeType) = "assignment" {
pavone@218 349 valassign <- quote: (val <- false)
pavone@218 350 valsym <- (valassign) symbol
pavone@218 351 valsym <- valsym name!: (valsym name) . ((el symbol) name)
pavone@218 352 valassign <- valassign symbol!: valsym
pavone@218 353 acc addExpression: valassign
pavone@218 354
pavone@218 355 matchassign <- quote: (hasmatch <- false)
pavone@218 356 matchsym <- (matchassign) symbol
pavone@218 357 matchsym <- matchsym name!: (matchsym name) . ((el symbol) name)
pavone@218 358 matchassign <- matchassign symbol!: matchsym
pavone@218 359 acc addExpression: matchassign
pavone@218 360
pavone@218 361 mc <- _makeMatchCall: (el expression)
pavone@218 362
pavone@218 363 if: (mc valid?) {
pavone@218 364 mcall <- mc matchcall
pavone@218 365 matchfun <- quote: :tomatch {
pavone@218 366 if: matchsym {
pavone@218 367 if: valsym = tomatch {
pavone@218 368 #{
pavone@218 369 matched? <- { true }
pavone@218 370 matchlen <- { valsym length }
pavone@218 371 basicYield? <- { true } //TODO: Check if this is correct
pavone@218 372 yield <- { valsym }
pavone@218 373 }
pavone@218 374 } else: {
pavone@218 375 #{
pavone@218 376 matched? <- { false }
pavone@218 377 }
pavone@218 378 }
pavone@218 379 } else: {
pavone@218 380 mr <- mcall
pavone@218 381 if: (mr matched?) {
pavone@218 382 matchsym <- true
pavone@218 383 valsym <- (mr yield)
pavone@218 384 }
pavone@218 385 mr
pavone@218 386 }
pavone@218 387 }
pavone@218 388 acc <- acc addExpression: (el expression!: matchfun)
pavone@218 389 syms <- list node: #{
pavone@218 390 orig <- el symbol
pavone@218 391 matchval <- valsym
pavone@218 392 } withTail: syms
pavone@218 393 acc
pavone@218 394 } else: {
pavone@218 395 print: "#error " . ((el symbol) name) . " does not have a valid match expression: " . (mc message) . "\n"
pavone@218 396 }
pavone@218 397
pavone@218 398 } else: {
pavone@218 399 print: "#error Nodes of type " . (el nodeType) . " are not allowed in match where clauses\n"
pavone@218 400 acc
pavone@218 401 }
pavone@218 402 }
pavone@218 403 mcMain <- _makeMatchCall: matchexpr
pavone@218 404 if: (mcMain valid?) {
pavone@218 405 mcall <- mcMain matchcall
pavone@218 406 withwhere addExpression: (quote: (matchres <- mcall))
pavone@218 407 successLambda <- quote: {
pavone@218 408 //Extra assignments will be added here
pavone@218 409 mlen <- matchres matchlen
pavone@218 410 #{
pavone@218 411 matched? <- { true }
pavone@218 412 matchlen <- { mlen }
pavone@218 413 basicYield? <- { false }
pavone@218 414 yield <- ylambda
pavone@218 415 }
pavone@218 416 }
pavone@218 417 sucexp <- syms fold: (successLambda expressions) with: :acc el {
pavone@218 418 lsym <- el orig
pavone@218 419 rsym <- el matchval
pavone@218 420 (quote: (lsym <- rsym)) | acc
pavone@218 421 }
pavone@218 422 successLambda <- successLambda expressions!: sucexp
pavone@218 423 withwhere addExpression: (quote: (if: (matchres matched?) successLambda else: {
pavone@218 424 matchres
pavone@218 425 }))
pavone@218 426 withwhere
pavone@218 427 } else: {
pavone@218 428 print: "#error Error in main match expression of match:where:yield: " . (mcMain message) . "\n"
pavone@218 429 }
pavone@218 430 }
pavone@218 431
pavone@225 432 binaryOps:withHigherPrec <- macro: :oplist :higher {
pavone@225 433 quote: (match: Left . Pieces where: {
pavone@225 434 Left <- match: higher
pavone@225 435 Pieces <- zeroPlus: (match: hws . Op . Right where: {
pavone@230 436 Op <- matchOne: oplist
pavone@230 437 Right <- match: higher
pavone@225 438 } yield: {
pavone@225 439 #{
pavone@225 440 op <- Op
pavone@225 441 right <- Right
pavone@225 442 }
pavone@225 443 })
pavone@225 444 } yield: {
pavone@225 445 _processOpPieces: Left Pieces
pavone@225 446 })
pavone@225 447 }
pavone@225 448
pavone@226 449 opexpr <- binaryOps: ["&&" "||"] withHigherPrec: compare
pavone@226 450 compare <- binaryOps: ["<=" ">=" "<" ">" "=" "!="] withHigherPrec: maybecons
pavone@226 451 maybecons <- matchOne: [
pavone@226 452 consop
pavone@226 453 addsub
pavone@226 454 ]
pavone@226 455 consop <- match: Left . hws . "|" . Right where: {
pavone@226 456 Left <- match: addsub
pavone@226 457 Right <- match: maybecons
pavone@226 458 } yield: {
pavone@226 459 #{
pavone@226 460 left <- Left
pavone@226 461 op <- "|"
pavone@226 462 right <- Right
pavone@227 463 string <- {
pavone@227 464 (string: left) . " " . op . " " . right
pavone@227 465 }
pavone@226 466 }
pavone@226 467 }
pavone@225 468 addsub <- binaryOps: ["+" "-" "."] withHigherPrec: muldiv
pavone@225 469 muldiv <- binaryOps: ["*" "/" "%"] withHigherPrec: primlitsym
pavone@225 470
pavone@225 471 //TODO: Implement operator expressions
pavone@226 472
pavone@209 473
pavone@209 474 _alpha <- charClass: "a-zA-Z"
pavone@209 475 alpha <- zeroPlus: _alpha
pavone@209 476 alphaNum <- zeroPlus: (charClass: "a-zA-Z0-9")
pavone@220 477
pavone@220 478 blockComment <- match: "/*" . (zeroPlus: (matchOne: [(charClass: "^*") "*" . (charClass: "^/")])) . "*/" yield: { false }
pavone@220 479
pavone@212 480 hws <- zeroPlus: (matchOne: [
pavone@212 481 (charClass: " \t")
pavone@220 482 blockComment
pavone@212 483 ])
pavone@212 484
pavone@220 485 ws <- zeroPlus: (matchOne: [
pavone@220 486 (charClass: " \n\t\r")
pavone@220 487 "//" . (zeroPlus: (charClass: "^\n")) . "\n"
pavone@220 488 blockComment
pavone@220 489 ])
pavone@220 490
pavone@220 491 escape <- matchOne: [
pavone@220 492 (match: "\\n" yield: {"\n"})
pavone@220 493 (match: "\\r" yield: {"\n"})
pavone@220 494 (match: "\\t" yield: {"\n"})
pavone@220 495 (match: "\\\\" yield: {"\\"})
pavone@220 496 (match: "\\\"" yield: {"\""})
pavone@213 497 ]
pavone@208 498
pavone@220 499 string <- match: "\"" . Chars . "\"" where: {
pavone@220 500 Chars <- zeroPlus: (matchOne: [
pavone@231 501 match: Reg where: { Reg <- charClass: "^\"\\" } yield: { Reg }
pavone@220 502 escape
pavone@220 503 ])
pavone@220 504 } yield: {
pavone@231 505 if: (Chars length) = 0 {
pavone@231 506 Chars <- []
pavone@231 507 }
pavone@220 508 Chars join: ""
pavone@220 509 }
pavone@220 510
pavone@220 511 bdigit <- matchOne: [
pavone@220 512 (match: "0" yield: {0i64})
pavone@220 513 (match: "1" yield: {1i64})
pavone@220 514 ]
pavone@220 515
pavone@220 516 digit <- matchOne: [
pavone@220 517 bdigit
pavone@220 518 (match: "2" yield: {2i64})
pavone@220 519 (match: "3" yield: {3i64})
pavone@220 520 (match: "4" yield: {4i64})
pavone@220 521 (match: "5" yield: {5i64})
pavone@220 522 (match: "6" yield: {6i64})
pavone@220 523 (match: "7" yield: {7i64})
pavone@220 524 (match: "8" yield: {8i64})
pavone@220 525 (match: "9" yield: {9i64})
pavone@220 526 ]
pavone@220 527
pavone@220 528 hdigit <- matchOne: [
pavone@220 529 digit
pavone@220 530 (match: (charClass: "aA") yield: {10i64})
pavone@220 531 (match: (charClass: "bB") yield: {11i64})
pavone@220 532 (match: (charClass: "cC") yield: {12i64})
pavone@220 533 (match: (charClass: "dD") yield: {13i64})
pavone@220 534 (match: (charClass: "eE") yield: {14i64})
pavone@220 535 (match: (charClass: "fF") yield: {15i64})
pavone@220 536 ]
pavone@220 537
pavone@220 538 binary <- match: "0b" . Digits . Suffix where: {
pavone@220 539 Digits <- onePlus: bdigit
pavone@220 540 Suffix <- matchOne: [
pavone@220 541 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
pavone@220 542 ""
pavone@220 543 ]
pavone@218 544 } yield: {
pavone@218 545 num <- Digits fold: 0 with: :acc el {
pavone@220 546 acc * 2i64 + el
pavone@220 547 }
pavone@220 548 signed <- true
pavone@220 549 litbits <- 32
pavone@220 550 if: (Suffix length) > 0 {
pavone@220 551 if: (Suffix from: 0 withLength: 1) = "u" {
pavone@220 552 signed <- false
pavone@220 553 }
pavone@220 554 litbits <- (Suffix from: 1) int32
pavone@218 555 }
pavone@218 556 #{
pavone@218 557 litval <- num
pavone@220 558 signed? <- signed
pavone@220 559 bits <- litbits
pavone@222 560 string <- {
pavone@222 561 str <- "0b"
pavone@222 562 i <- bits - 1
pavone@222 563 printzero <- false
pavone@222 564 while: { i >= 0 } do: {
pavone@222 565 str <- str . (if: (lshift: 1 by: i) and num > 0 {
pavone@222 566 printzero <- true
pavone@222 567 "1"
pavone@222 568 } else: {
pavone@222 569 if: printzero {"0"} else: {""}
pavone@222 570 })
pavone@222 571 i <- i - 1
pavone@222 572 }
pavone@222 573 if: (not: signed?) || bits != 32 {
pavone@222 574 str <- str . (if: signed { "i" } else: { "u" }) . bits
pavone@222 575 }
pavone@222 576 str
pavone@222 577 }
pavone@220 578 }
pavone@220 579 }
pavone@220 580
pavone@220 581 decimal <- match: Sign . Digits . Suffix where: {
pavone@220 582 Sign <- matchOne: ["-" ""]
pavone@220 583 Digits <- onePlus: digit
pavone@220 584 Suffix <- matchOne: [
pavone@220 585 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
pavone@220 586 ""
pavone@220 587 ]
pavone@220 588 } yield: {
pavone@220 589 num <- Digits fold: 0 with: :acc el {
pavone@220 590 acc * 10i64 + el
pavone@220 591 }
pavone@220 592 if: Sign = "-" {
pavone@220 593 num <- 0i64 - num
pavone@220 594 }
pavone@220 595 signed <- true
pavone@220 596 litbits <- 32
pavone@220 597 if: (Suffix length) > 0 {
pavone@220 598 if: (Suffix from: 0 withLength: 1) = "u" {
pavone@220 599 signed <- false
pavone@220 600 }
pavone@220 601 print: (Suffix from: 1) . "\n"
pavone@220 602 litbits <- (Suffix from: 1) int32
pavone@220 603 }
pavone@220 604 #{
pavone@220 605 litval <- num
pavone@220 606 signed? <- signed
pavone@220 607 bits <- litbits
pavone@222 608 string <- {
pavone@222 609 str <- string: litval
pavone@222 610 if: (not: signed?) || bits != 32 {
pavone@222 611 str <- str . (if: signed? {"i"} else: {"u"}) . bits
pavone@222 612 }
pavone@222 613 str
pavone@222 614 }
pavone@220 615 }
pavone@220 616 }
pavone@220 617
pavone@222 618 hexlit <- match: "0x" . Digits . Suffix where: {
pavone@220 619 Digits <- onePlus: hdigit
pavone@220 620 Suffix <- matchOne: [
pavone@220 621 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
pavone@220 622 ""
pavone@220 623 ]
pavone@220 624 } yield: {
pavone@220 625 num <- Digits fold: 0 with: :acc el {
pavone@220 626 acc * 16i64 + el
pavone@220 627 }
pavone@220 628 signed <- true
pavone@220 629 litbits <- 32
pavone@220 630 if: (Suffix length) > 0 {
pavone@220 631 if: (Suffix from: 0 withLength: 1) = "u" {
pavone@220 632 signed <- false
pavone@220 633 }
pavone@220 634 litbits <- (Suffix from: 1) int32
pavone@220 635 }
pavone@220 636 #{
pavone@220 637 litval <- num
pavone@220 638 signed? <- signed
pavone@220 639 bits <- litbits
pavone@222 640 string <- {
pavone@222 641 str <- "0x" . (hex: litval)
pavone@222 642 if: (not: signed?) || bits != 32 {
pavone@222 643 str <- str . (if: signed? {"i"} else: {"u"}) . bits
pavone@222 644 }
pavone@222 645 str
pavone@222 646 }
pavone@220 647 }
pavone@220 648 }
pavone@220 649
pavone@222 650 symexpr <- match: Name where: {
pavone@222 651 Name <- match: (onePlus: (charClass: "a-zA-Z_@!?")) . (zeroPlus: ((matchOne: [":" ""]) . (charClass: "a-zA-Z_@!?0-9")))
pavone@222 652 } yield: {
pavone@222 653 #{
pavone@222 654 name <- Name
pavone@222 655 string <- {
pavone@222 656 name
pavone@222 657 }
pavone@222 658 }
pavone@222 659 }
pavone@222 660
pavone@222 661 namepart <- match: hws . Symbol . ":" where: {
pavone@222 662 Symbol <- match: symexpr
pavone@222 663 } yield: {
pavone@222 664 #{
pavone@222 665 isNamePart? <- { true }
pavone@222 666 val <- Symbol name
pavone@222 667 }
pavone@222 668 }
pavone@222 669
pavone@222 670 argpart <- matchOne: [
pavone@222 671 match: namepart
pavone@222 672 match: Arg where: {
pavone@222 673 Arg <- opexpr
pavone@222 674 } yield: {
pavone@222 675 #{
pavone@222 676 isNamePart? <- { false }
pavone@222 677 val <- Arg
pavone@222 678 }
pavone@222 679 }
pavone@222 680 ]
pavone@222 681
pavone@222 682 funcall <- match: hws . Initial . Parts where: {
pavone@222 683 Initial <- match: namepart
pavone@222 684 Parts <- onePlus: argpart
pavone@222 685 } yield: {
pavone@222 686 Initial | Parts foldr: #{
pavone@222 687 name <- ""
pavone@222 688 args <- []
pavone@222 689 } with: :acc el {
pavone@222 690 nextName <- acc name
pavone@222 691 nextArgs <- acc args
pavone@222 692 if: (el isNamePart?) {
pavone@222 693 nextName <- if: ((acc name) length) > 0 { (el val) . ":" . (acc name) } else: { el val }
pavone@222 694 } else: {
pavone@222 695 nextArgs <- (el val) | nextArgs
pavone@222 696 }
pavone@222 697
pavone@222 698 #{
pavone@222 699 name <- nextName
pavone@222 700 args <- nextArgs
pavone@222 701 string <- {
pavone@222 702 str <- ""
pavone@222 703 curArgs <- args
pavone@222 704 nameParts <- name splitOn: ":"
pavone@232 705 foreach: nameParts :idx part {
pavone@222 706 str <- str . part . ":"
pavone@222 707 if: (not: (curArgs empty?)) {
pavone@222 708 str <- str . " " . (curArgs value)
pavone@222 709 curArgs <- curArgs tail
pavone@222 710 }
pavone@222 711 }
pavone@235 712 while: { not: (curArgs empty?) } do: {
pavone@235 713 str <- str . " " . (curArgs value)
pavone@235 714 curArgs <- curArgs tail
pavone@235 715 }
pavone@222 716 str
pavone@222 717 }
pavone@222 718 }
pavone@222 719 }
pavone@222 720 }
pavone@222 721
pavone@227 722 unarymeth <- match: Receiver . hws . Method where: {
pavone@227 723 Receiver <- match: opexpr
pavone@227 724 Method <- match: symexpr
pavone@227 725 } yield: {
pavone@227 726 #{
pavone@227 727 receiver <- Receiver
pavone@227 728 name <- Method name
pavone@227 729 args <- []
pavone@234 730 string <- {
pavone@234 731 (string: receiver) . " " . name
pavone@234 732 }
pavone@227 733 }
pavone@227 734 }
pavone@227 735
pavone@222 736 methcall <- match: Receiver . hws . Rest where: {
pavone@222 737 Receiver <- match: opexpr
pavone@227 738 Rest <- match: funcall
pavone@222 739 } yield: {
pavone@222 740 #{
pavone@222 741 receiver <- Receiver
pavone@222 742 name <- Rest name
pavone@222 743 args <- Rest args
pavone@222 744 string <- {
pavone@222 745 nameParts <- name splitOn: ":"
pavone@222 746 curArgs <- args
pavone@222 747 str <- (string: receiver) . " "
pavone@222 748 foreach: nameParts :part {
pavone@222 749 str <- str . part . ":"
pavone@222 750 if: (not: (curArgs empty?)) {
pavone@222 751 str <- str . " " . (curArgs value)
pavone@222 752 curArgs <- curArgs tail
pavone@222 753 }
pavone@222 754 }
pavone@235 755 while: { not: (curArgs empty?) } do: {
pavone@235 756 str <- str . " " . (curArgs value)
pavone@235 757 curArgs <- curArgs tail
pavone@235 758 }
pavone@222 759 str
pavone@222 760 }
pavone@222 761 }
pavone@222 762 }
pavone@223 763 _processOpPieces <- :Left Pieces {
pavone@223 764 if: (Pieces length) > 0 {
pavone@223 765 Pieces fold: Left with: :acc piece {
pavone@223 766 #{
pavone@223 767 left <- acc
pavone@223 768 op <- piece op
pavone@223 769 right <- piece right
pavone@223 770 string <- {
pavone@223 771 (string: left) . " " . op . " " . right
pavone@223 772 }
pavone@223 773 }
pavone@223 774 }
pavone@223 775 } else: {
pavone@223 776 Left
pavone@223 777 }
pavone@223 778 }
pavone@223 779
pavone@222 780 expr <- match: (hws . Expr . ws) where: {
pavone@222 781 Expr <- matchOne: [
pavone@222 782 funcall
pavone@222 783 methcall
pavone@227 784 unarymeth
pavone@230 785 assignment
pavone@227 786 opexpr
pavone@227 787 ]
pavone@227 788 } yield: {
pavone@227 789 Expr
pavone@227 790 }
pavone@227 791
pavone@227 792 lexpr <- match: (hws . Expr . ws) where: {
pavone@227 793 Expr <- matchOne: [
pavone@227 794 funcall
pavone@227 795 methcall
pavone@222 796 opexpr
pavone@222 797 ]
pavone@222 798 } yield: {
pavone@222 799 Expr
pavone@222 800 }
pavone@222 801
pavone@222 802 assignment <- match: ws . Symbol . hws . "<-" . Expr where: {
pavone@222 803 Symbol <- match: symexpr
pavone@222 804 Expr <- match: expr
pavone@222 805 } yield: {
pavone@222 806 #{
pavone@222 807 assign <- Expr
pavone@222 808 to <- Symbol
pavone@222 809 string <- {
pavone@222 810 (string: to) . " <- " . assign
pavone@222 811 }
pavone@222 812 }
pavone@222 813 }
pavone@222 814
pavone@222 815 object <- match: "#{" . ws . Messages . "}" where: {
pavone@222 816 Messages <- zeroPlus: assignment
pavone@222 817 } yield: {
pavone@222 818 #{
pavone@222 819 messages <- Messages
pavone@222 820 string <- {
pavone@222 821 "#{\n\t". ((messages map: :el {
pavone@222 822 string: el
pavone@222 823 }) join: "\n\t") . "\n}"
pavone@222 824 }
pavone@222 825 }
pavone@222 826 }
pavone@222 827
pavone@227 828 listlit <- match: "[" . ws . Els . "]" where: {
pavone@227 829 Els <- zeroPlus: lexpr
pavone@227 830 } yield: {
pavone@227 831 //Handle limitation of zeroPlus macro
pavone@227 832 if: (Els length) = 0 {
pavone@227 833 Els <- []
pavone@227 834 }
pavone@227 835 #{
pavone@227 836 litval <- Els
pavone@227 837 string <- {
pavone@227 838 "[\n\t". ((litval map: :el {
pavone@227 839 string: el
pavone@227 840 }) join: "\n\t") . "\n]"
pavone@227 841 }
pavone@227 842 }
pavone@227 843 }
pavone@227 844
pavone@228 845 arraylit <- match: "#[" . ws . Els . "]" where: {
pavone@228 846 Els <- zeroPlus: lexpr
pavone@228 847 } yield: {
pavone@228 848 //Handle limitation of zeroPlus macro
pavone@228 849 if: (Els length) = 0 {
pavone@228 850 Els <- []
pavone@228 851 }
pavone@228 852 #{
pavone@228 853 litval <- Els
pavone@228 854 string <- {
pavone@228 855 "#[\n\t". ((litval map: :el {
pavone@228 856 string: el
pavone@228 857 }) join: "\n\t") . "\n]"
pavone@228 858 }
pavone@228 859 }
pavone@228 860 }
pavone@228 861
pavone@230 862 argname <- match: hws . Pre . Initial . Rest where: {
pavone@230 863 Pre <- matchOne: [":" ""]
pavone@230 864 Initial <- onePlus: (charClass: "a-zA-Z_!?@")
pavone@230 865 Rest <- zeroPlus: (charClass: "a-zA-Z_!?@0-9")
pavone@230 866 } yield: {
pavone@230 867 Pre . Initial . Rest
pavone@230 868 }
pavone@230 869
pavone@230 870 lambda <- match: hws . Arglist . hws . "{" . ws . Exprs . "}" where: {
pavone@230 871 Arglist <- matchOne: [
pavone@230 872 match: ":" . First . Rest where: {
pavone@230 873 First <- match: symexpr
pavone@230 874 Rest <- zeroPlus: argname
pavone@230 875 } yield: {
pavone@230 876 if: (Rest length) = 0 {
pavone@230 877 Rest <- []
pavone@230 878 }
pavone@230 879 ":" . (First name) | Rest
pavone@230 880 }
pavone@230 881 match: "" yield: { [] }
pavone@230 882 ]
pavone@230 883 Exprs <- zeroPlus: expr
pavone@230 884 } yield: {
pavone@230 885 if: (Exprs length) = 0 {
pavone@230 886 Exprs <- []
pavone@230 887 }
pavone@230 888 #{
pavone@230 889 args <- Arglist
pavone@230 890 expressions <- Exprs
pavone@230 891 string <- {
pavone@230 892 (args join: " ") . "{\n\t" .
pavone@230 893 ((expressions map: :el { string: el }) join: "\n\t") .
pavone@230 894 "}"
pavone@230 895 }
pavone@230 896 }
pavone@230 897 }
pavone@230 898
pavone@231 899 parenexp <- match: "(" . ws . Expr . ws . ")" where: {
pavone@231 900 Expr <- match: expr
pavone@231 901 } yield: {
pavone@231 902 Expr
pavone@231 903 }
pavone@231 904
pavone@222 905 primlitsym <- match: hws . Lit where: {
pavone@222 906 Lit <- matchOne: [
pavone@222 907 hexlit
pavone@222 908 binary
pavone@222 909 decimal
pavone@222 910 symexpr
pavone@230 911 lambda
pavone@222 912 object
pavone@227 913 listlit
pavone@228 914 arraylit
pavone@231 915 string
pavone@231 916 parenexp
pavone@222 917 ]
pavone@222 918 } yield: {
pavone@222 919 Lit
pavone@222 920 }
pavone@222 921
pavone@231 922 top <- matchOne: [
pavone@231 923 object
pavone@231 924 lambda
pavone@231 925 ]
pavone@231 926
pavone@220 927 testmatchintlit <- :val matchfun {
pavone@220 928 res <- matchfun: val
pavone@220 929 if: (res matched?) {
pavone@220 930 y <- res yield
pavone@220 931 print: val . " matched with litval " . (y litval) . ", bits " . (y bits) . " and singned? " . (y signed?) . "\n"
pavone@220 932 } else: {
pavone@220 933 print: val . " did not match\n"
pavone@218 934 }
pavone@218 935 }
pavone@218 936
pavone@231 937 main <- :args {
pavone@209 938 cmatch <- alpha: "czx0123"
pavone@208 939 zeromatch <- alpha: "01234"
pavone@208 940 if: (cmatch matched?) {
pavone@209 941 print: "czx0123 matched with length " . (cmatch matchlen) . "\n"
pavone@208 942 } else: {
pavone@209 943 print: "czx0123 didn't match\n"
pavone@208 944 }
pavone@208 945 if: (zeromatch matched?) {
pavone@208 946 print: "0123 matched with length " . (zeromatch matchlen) . "\n"
pavone@208 947 } else: {
pavone@208 948 print: "0123 didn't match\n"
pavone@208 949 }
pavone@209 950 zeromatchanum <- alphaNum: "01234"
pavone@209 951 if: (zeromatchanum matched?) {
pavone@209 952 print: "01234 matched with length " . (zeromatchanum matchlen) . "\n"
pavone@209 953 } else: {
pavone@209 954 print: "01234 didn't match\n"
pavone@209 955 }
pavone@212 956 stuff <- " \t/* blah blah blah * blah */ foo"
pavone@212 957 hwsmatch <- hws: stuff
pavone@212 958 if: (hwsmatch matched?) {
pavone@212 959 print: "'" . (stuff from: (hwsmatch matchlen)) . "' found after hws\n"
pavone@212 960 } else: {
pavone@212 961 print: stuff . " did not match hws rule\n"
pavone@212 962 }
pavone@213 963 tmatch <- digit: "3"
pavone@213 964 if: (tmatch matched?) {
pavone@213 965 print: "3 matched with yield " . (tmatch yield) . ", yield + 1 = " . ((tmatch yield) + 1) . "\n"
pavone@213 966 } else: {
pavone@213 967 print: "3 did not match\n"
pavone@213 968 }
pavone@218 969
pavone@220 970 testmatchintlit: "345" :s {decimal: s}
pavone@220 971 testmatchintlit: "-567" :s {decimal: s}
pavone@220 972 testmatchintlit: "123u16" :s {decimal: s}
pavone@222 973 testmatchintlit: "0x20" :s {hexlit: s}
pavone@222 974 testmatchintlit: "0x42u64" :s {hexlit: s}
pavone@220 975 testmatchintlit: "0b10101" :s {binary: s}
pavone@230 976 code <- "#{ foo <- 123 > 0x42 && 42 < 104\n bar <- 0xABC + 0b1010101\n baz <- 0b1010 * 5\n qux <- fo: 38 shizzle: bam\n quine <- 123 | [4 5 6 fiddle sticks]\n quizzle <- #[receiver meth: arg]\n blah <- :arg arg2 :arg3 { arg + arg2 + arg3 }}"
pavone@231 977 if: (args length) > 1 {
pavone@231 978 file <- os open: (args get: 1) (os O_RDONLY)
pavone@236 979 code <- ""
pavone@236 980 chunksize <- 1024
pavone@236 981 readsize <- chunksize
pavone@236 982 while: { readsize = chunksize} do: {
pavone@236 983 seg <- os read: file chunksize
pavone@236 984 code <- code . seg
pavone@236 985 readsize <- seg byte_length
pavone@236 986 }
pavone@231 987 }
pavone@231 988 codem <- top: code
pavone@222 989 if: (codem matched?) {
pavone@222 990 print: code . "\nmatched with yield:\n" . (codem yield) . "\n"
pavone@222 991 } else: {
pavone@222 992 print: code . "\ndid not match\n"
pavone@222 993 }
pavone@208 994 }
pavone@208 995 }