comparison modules/parser.tp @ 220:a1a80af71b05

Implement onePlus macro. Fix some bugs in the other matching macros. Implement integer literal parsing rules.
author Michael Pavone <pavone@retrodev.com>
date Mon, 23 Dec 2013 14:44:31 -0800
parents b799192e404b
children c6e321a538d4
comparison
equal deleted inserted replaced
219:b70be565d54c 220:a1a80af71b05
64 #{ 64 #{
65 valid? <- { true } 65 valid? <- { true }
66 matchcall <- quote: (_applyMatch: :tomatch { 66 matchcall <- quote: (_applyMatch: :tomatch {
67 lm <- left 67 lm <- left
68 if: (lm matched?) { 68 if: (lm matched?) {
69 orig <- tomatch
69 tomatch <- tomatch from: (lm matchlen) 70 tomatch <- tomatch from: (lm matchlen)
70 rm <- right 71 rm <- right
71 if: (rm matched?) { 72 if: (rm matched?) {
72 total <- (rm matchlen) + (lm matchlen) 73 total <- (rm matchlen) + (lm matchlen)
73 #{ 74 #{
74 matched? <- { true } 75 matched? <- { true }
75 matchlen <- { total } 76 matchlen <- { total }
76 basicYield? <- { true } 77 basicYield? <- { true }
77 yield <- { tomatch from: 0 withLen: total } 78 yield <- { orig from: 0 withLength: total }
78 } 79 }
79 } else: { 80 } else: {
80 rm 81 rm
81 } 82 }
82 } else: { 83 } else: {
206 } else: { 207 } else: {
207 print: "#error Argument to charClass macro must be a compile-time constant\n" 208 print: "#error Argument to charClass macro must be a compile-time constant\n"
208 } 209 }
209 } 210 }
210 211
211 zeroPlus <- macro: :matchexpr { 212 _nPlus <- :matchexpr min {
212 funexpr <- false 213 funexpr <- false
213 valid <- false 214 valid <- false
214 mc <- _makeMatchCall: matchexpr 215 mc <- _makeMatchCall: matchexpr
215 if: (mc valid?) { 216 if: (mc valid?) {
216 mcall <- mc matchcall 217 mcall <- mc matchcall
217 quote: :tomatch { 218 quote: :tomatch {
218 cur <- 0 219 cur <- 0
220 count <- 0
219 n <- tomatch byte_length 221 n <- tomatch byte_length
220 orig <- tomatch 222 orig <- tomatch
221 match <- true 223 match <- true
222 allBasic? <- true 224 allBasic? <- true
223 yieldvals <- [] 225 yieldvals <- []
224 while: { match && cur < n } do: { 226 while: { match && cur < n } do: {
225 res <- mcall 227 res <- mcall
226 match <- res matched? 228 match <- res matched?
227 if: match { 229 if: match {
230 count <- count + 1
228 //TODO: Use some kind of lightweight substring wrapper here 231 //TODO: Use some kind of lightweight substring wrapper here
229 tomatch <- tomatch from: (res matchlen) 232 tomatch <- tomatch from: (res matchlen)
230 if: allBasic? { 233 if: allBasic? {
231 ifnot: (res basicYield?) { 234 ifnot: (res basicYield?) {
232 allBasic? <- false 235 allBasic? <- false
240 } 243 }
241 allBasic? <- allBasic? && (res basicYield?) 244 allBasic? <- allBasic? && (res basicYield?)
242 cur <- cur + (res matchlen) 245 cur <- cur + (res matchlen)
243 } 246 }
244 } 247 }
245 if: cur > 0 { 248 if: count >= min {
246 if: allBasic? { 249 if: allBasic? {
247 #{ 250 #{
248 matched? <- { true } 251 matched? <- { true }
249 matchlen <- { cur } 252 matchlen <- { cur }
250 basicYield? <- { true } 253 basicYield? <- { true }
264 matched? <- { false } 267 matched? <- { false }
265 } 268 }
266 } 269 }
267 } 270 }
268 } else: { 271 } else: {
269 print: "#error Invalid zeroPlus macro call: " . (mc message) . "\n" 272 print: "#error Invalid nPlus macro call: " . (mc message) . "\n"
270 } 273 }
274 }
275
276 zeroPlus <- macro: :matchexpr {
277 _nPlus: matchexpr 0
278 }
279
280 onePlus <- macro: :matchexpr {
281 _nPlus: matchexpr 1
271 } 282 }
272 283
273 matchOne <- macro: :options { 284 matchOne <- macro: :options {
274 options <- (options value) map: :option { 285 options <- (options value) map: :option {
275 _makeMatchCall: option 286 _makeMatchCall: option
402 413
403 414
404 _alpha <- charClass: "a-zA-Z" 415 _alpha <- charClass: "a-zA-Z"
405 alpha <- zeroPlus: _alpha 416 alpha <- zeroPlus: _alpha
406 alphaNum <- zeroPlus: (charClass: "a-zA-Z0-9") 417 alphaNum <- zeroPlus: (charClass: "a-zA-Z0-9")
418
419 blockComment <- match: "/*" . (zeroPlus: (matchOne: [(charClass: "^*") "*" . (charClass: "^/")])) . "*/" yield: { false }
420
407 hws <- zeroPlus: (matchOne: [ 421 hws <- zeroPlus: (matchOne: [
408 (charClass: " \t") 422 (charClass: " \t")
409 "/*" . (zeroPlus: (matchOne: [(charClass: "^*") "*" . (charClass: "^/")])) . "*/" 423 blockComment
410 ]) 424 ])
411 425
426 ws <- zeroPlus: (matchOne: [
427 (charClass: " \n\t\r")
428 "//" . (zeroPlus: (charClass: "^\n")) . "\n"
429 blockComment
430 ])
431
432 escape <- matchOne: [
433 (match: "\\n" yield: {"\n"})
434 (match: "\\r" yield: {"\n"})
435 (match: "\\t" yield: {"\n"})
436 (match: "\\\\" yield: {"\\"})
437 (match: "\\\"" yield: {"\""})
438 ]
439
440 string <- match: "\"" . Chars . "\"" where: {
441 Chars <- zeroPlus: (matchOne: [
442 (charClass: "^\"\\")
443 escape
444 ])
445 } yield: {
446 Chars join: ""
447 }
448
449 bdigit <- matchOne: [
450 (match: "0" yield: {0i64})
451 (match: "1" yield: {1i64})
452 ]
453
412 digit <- matchOne: [ 454 digit <- matchOne: [
413 (match: "0" yield: {0}) 455 bdigit
414 (match: "1" yield: {1}) 456 (match: "2" yield: {2i64})
415 (match: "2" yield: {2}) 457 (match: "3" yield: {3i64})
416 (match: "3" yield: {3}) 458 (match: "4" yield: {4i64})
417 (match: "4" yield: {4}) 459 (match: "5" yield: {5i64})
418 (match: "5" yield: {5}) 460 (match: "6" yield: {6i64})
419 (match: "6" yield: {6}) 461 (match: "7" yield: {7i64})
420 (match: "7" yield: {7}) 462 (match: "8" yield: {8i64})
421 (match: "8" yield: {8}) 463 (match: "9" yield: {9i64})
422 (match: "9" yield: {9})
423 ] 464 ]
424 465
425 posint <- match: Digits where: { 466 hdigit <- matchOne: [
426 Digits <- zeroPlus: digit 467 digit
468 (match: (charClass: "aA") yield: {10i64})
469 (match: (charClass: "bB") yield: {11i64})
470 (match: (charClass: "cC") yield: {12i64})
471 (match: (charClass: "dD") yield: {13i64})
472 (match: (charClass: "eE") yield: {14i64})
473 (match: (charClass: "fF") yield: {15i64})
474 ]
475
476 binary <- match: "0b" . Digits . Suffix where: {
477 Digits <- onePlus: bdigit
478 Suffix <- matchOne: [
479 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
480 ""
481 ]
427 } yield: { 482 } yield: {
428 num <- Digits fold: 0 with: :acc el { 483 num <- Digits fold: 0 with: :acc el {
429 print: "Element " . el . "\n" 484 acc * 2i64 + el
430 acc * 10 + el 485 }
486 signed <- true
487 litbits <- 32
488 if: (Suffix length) > 0 {
489 if: (Suffix from: 0 withLength: 1) = "u" {
490 signed <- false
491 }
492 litbits <- (Suffix from: 1) int32
431 } 493 }
432 #{ 494 #{
433 litval <- num 495 litval <- num
496 signed? <- signed
497 bits <- litbits
498 }
499 }
500
501 decimal <- match: Sign . Digits . Suffix where: {
502 Sign <- matchOne: ["-" ""]
503 Digits <- onePlus: digit
504 Suffix <- matchOne: [
505 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
506 ""
507 ]
508 } yield: {
509 num <- Digits fold: 0 with: :acc el {
510 acc * 10i64 + el
511 }
512 if: Sign = "-" {
513 num <- 0i64 - num
514 }
515 signed <- true
516 litbits <- 32
517 if: (Suffix length) > 0 {
518 if: (Suffix from: 0 withLength: 1) = "u" {
519 signed <- false
520 }
521 print: (Suffix from: 1) . "\n"
522 litbits <- (Suffix from: 1) int32
523 }
524 #{
525 litval <- num
526 signed? <- signed
527 bits <- litbits
528 }
529 }
530
531 hex <- match: "0x" . Digits . Suffix where: {
532 Digits <- onePlus: hdigit
533 Suffix <- matchOne: [
534 (charClass: "ui") . (matchOne: ["8" "16" "32" "64"])
535 ""
536 ]
537 } yield: {
538 num <- Digits fold: 0 with: :acc el {
539 acc * 16i64 + el
540 }
541 signed <- true
542 litbits <- 32
543 if: (Suffix length) > 0 {
544 if: (Suffix from: 0 withLength: 1) = "u" {
545 signed <- false
546 }
547 litbits <- (Suffix from: 1) int32
548 }
549 #{
550 litval <- num
551 signed? <- signed
552 bits <- litbits
553 }
554 }
555
556 testmatchintlit <- :val matchfun {
557 res <- matchfun: val
558 if: (res matched?) {
559 y <- res yield
560 print: val . " matched with litval " . (y litval) . ", bits " . (y bits) . " and singned? " . (y signed?) . "\n"
561 } else: {
562 print: val . " did not match\n"
434 } 563 }
435 } 564 }
436 565
437 main <- { 566 main <- {
438 cmatch <- alpha: "czx0123" 567 cmatch <- alpha: "czx0123"
465 print: "3 matched with yield " . (tmatch yield) . ", yield + 1 = " . ((tmatch yield) + 1) . "\n" 594 print: "3 matched with yield " . (tmatch yield) . ", yield + 1 = " . ((tmatch yield) + 1) . "\n"
466 } else: { 595 } else: {
467 print: "3 did not match\n" 596 print: "3 did not match\n"
468 } 597 }
469 598
470 posintm <- posint: "345" 599 testmatchintlit: "345" :s {decimal: s}
471 if: (posintm matched?) { 600 testmatchintlit: "-567" :s {decimal: s}
472 print: "345 matched with intlit value " . ((posintm yield) litval) . "\n" 601 testmatchintlit: "123u16" :s {decimal: s}
473 } else: { 602 testmatchintlit: "0x20" :s {hex: s}
474 print: "345 did not match\n" 603 testmatchintlit: "0x42u64" :s {hex: s}
475 } 604 testmatchintlit: "0b10101" :s {binary: s}
476 } 605 }
477 } 606 }