annotate modules/parser.tp @ 256:03a07e540b9f

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