Mercurial > repos > tabletprog
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 } |