annotate modules/parser.tp @ 245:3590ecca6bc9

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