Annotation of gforth/gray.fs, revision 1.1
1.1 ! anton 1: \ Copyright 1990 Martin Anton Ertl
! 2: \
! 3: \ TERMS AND CONDITIONS FOR USE, COPYING, MODIFICATION AND DISTRIBUTION
! 4: \
! 5: \ 1. You may use this product provided that
! 6: \ a) you DO NOT USE IT FOR MILITARY PURPOSES; and
! 7: \ b) cause the terms of parapraph 1 to apply to any products
! 8: \ developed using this product and make these terms known to all
! 9: \ users of such product;
! 10: \ By using this product, you indicate the acceptance of the terms of
! 11: \ this paragraph.
! 12: \
! 13: \ 2. Except for the restrictions mentioned in paragraph 1, you may use
! 14: \ the Program.
! 15: \
! 16: \ 3. You may distribute verbatim or modified copies of this program,
! 17: \ provided that
! 18: \ a) you keep intact all copyright notices, this license, and the notices
! 19: \ referring to this license and to the absence of warranty; and
! 20: \ b) you cause any work that you distribute or publish that contains the
! 21: \ Program or part of it to be licensed to all third parties under the
! 22: \ terms of this license. You may not impose any further restriction
! 23: \ on the recipients exercise of the rights granted herein. Mere
! 24: \ aggregation of another independent work with the Program or its
! 25: \ derivative on a volume of storage or distribution medium does not
! 26: \ bring the other work under the scope of these terms; and
! 27: \ c) you cause the derivative to carry prominent notices saying that
! 28: \ you changed the Program.
! 29: \
! 30: \ 4. You may distribute the Program or its derivative in intermediate,
! 31: \ object or executable code, if you accompany it with the complete
! 32: \ machine-readable source code.
! 33: \
! 34: \ 5. By using, modifying, copying or distributing the Program you
! 35: \ indicate your acceptance of this license and all its terms and
! 36: \ conditions.
! 37: \
! 38: \ 6. This Program is provided WITHOUT WARRANTY of any kind, either
! 39: \ express or implied, including, but not limited to, the implied
! 40: \ warranties of merchantability and fitness for a particular purpose. In
! 41: \ no event, unless required by applicable law or agreed to in writing,
! 42: \ will any copyright holder, or any other party who may modify and or
! 43: \ redistribute the Program, be liable to you for any damages, even if
! 44: \ such holder or other party has been advised of the possibility of such
! 45: \ damages.
! 46: \ END OF TERMS AND CONDITIONS )
! 47:
! 48: \ recursive descent parser generator )
! 49:
! 50: .( Loading Gray ... Copyright 1990 Martin Anton Ertl; NO WARRANTY ) cr
! 51:
! 52: \ misc )
! 53: : noop ;
! 54:
! 55: 1 cells constant cell
! 56: cell 8 * constant bits/cell \ !! implementation dependent )
! 57:
! 58: : ?not? ( f -- f )
! 59: 0= ;
! 60:
! 61: : 2, ( w1 w2 -- )
! 62: here 2 cells allot 2! ;
! 63:
! 64: : endif postpone then ; immediate
! 65:
! 66: : ?pairs ( n1 n2 -- )
! 67: ( aborts, if the numbers are not equal )
! 68: = ?not? abort" mismatched parenthesis" ;
! 69:
! 70: : ', \ -- ) ( use: ', name )
! 71: ' , ;
! 72:
! 73: 1 0= constant false
! 74: 0 0= constant true
! 75:
! 76: \ stack administration )
! 77: \ this implementation is completely unsafe )
! 78:
! 79: : stack \ n -- )
! 80: \ use: n stack word )
! 81: \ creates a stack called word with n cells )
! 82: \ the first cell is the stackpointer )
! 83: create here , cells allot ;
! 84:
! 85: : push \ n stack -- )
! 86: cell over +! @ ! ;
! 87:
! 88: : top \ stack -- n )
! 89: @ @ ;
! 90:
! 91: : pop \ stack -- )
! 92: [ -1 cells ] literal swap +! ;
! 93:
! 94: : clear? \ stack -- f )
! 95: dup @ = ;
! 96:
! 97: : clear \ stack -- )
! 98: dup ! ;
! 99:
! 100:
! 101: \ sets - represented as bit arrays )
! 102: \ bits that represent no elements, must be 0 )
! 103: \ all operations assume valid parameters )
! 104: \ elements must be unsigned numbers )
! 105: \ the max. element size must be declared with max-member )
! 106: \ no checking is performed )
! 107: \ set operations allot memory )
! 108:
! 109: : decode \ u -- w )
! 110: \ returns a cell with bit# u set and everyting else clear )
! 111: 1 swap lshift ;
! 112:
! 113: variable cells/set 0 cells/set !
! 114: variable empty-ptr 0 empty-ptr ! \ updatd by max-member )
! 115: : empty \ -- set )
! 116: empty-ptr @ ;
! 117:
! 118: : max-member \ u -- )
! 119: \ declares u to be the maximum member of sets generated afterwards )
! 120: \ must be called before using any set word except member?, add-member )
! 121: bits/cell / 1+
! 122: dup cells/set !
! 123: here empty-ptr ! \ make empty set )
! 124: 0 do 0 , loop ;
! 125:
! 126: : copy-set \ set1 -- set2 )
! 127: \ makes a copy of set1 )
! 128: here swap
! 129: cells/set @ 0 do
! 130: dup @ ,
! 131: cell+ loop
! 132: drop ;
! 133:
! 134: : normalize-bit-addr \ addr1 u1 -- addr2 u2 )
! 135: \ addr1*bits/cell+u1=addr2*bits/cell+u2, u2<bits/cell )
! 136: bits/cell /mod
! 137: cells rot +
! 138: swap ;
! 139:
! 140: : add-member \ u set -- )
! 141: \ changes set to include u )
! 142: swap normalize-bit-addr
! 143: decode
! 144: over @ or swap ! ;
! 145:
! 146: : singleton \ u -- set )
! 147: \ makes a set that contains u and nothing else )
! 148: empty copy-set swap over add-member ;
! 149:
! 150: : member? \ set u -- f )
! 151: \ returns true if u is in set )
! 152: normalize-bit-addr
! 153: decode
! 154: swap @ and
! 155: 0= ?not? ;
! 156:
! 157: : binary-set-operation \ set1 set2 [w1 w2 -- w3] -- set )
! 158: \ creates set from set1 and set2 by applying [w1 w2 -- w3] on members )
! 159: \ e.g. ' or binary-set-operation is the union operation )
! 160: here >r
! 161: cells/set @ 0 do >r
! 162: over @ over @ r@ execute ,
! 163: cell+ swap cell+ swap
! 164: r> loop
! 165: drop 2drop r> ;
! 166:
! 167: : union1 \ set1 set2 -- set )
! 168: ['] or binary-set-operation ;
! 169:
! 170: : intersection \ set1 set2 -- set )
! 171: ['] and binary-set-operation ;
! 172:
! 173: : binary-set-test? \ set1 set2 [w1 w2 -- w3] -- f )
! 174: \ returns true, if [w1 w2 -- w3] binary-set-operation returns empty )
! 175: \ e.g. set1 set2 ' and binary-set-test? is true, if set1 and set2
! 176: \ are disjoint, i.e. they contain no common members )
! 177: >r true rot rot r>
! 178: cells/set @ 0 do >r
! 179: over @ over @ r@ execute 0= ?not? if
! 180: rot drop false rot rot
! 181: endif
! 182: cell+ swap cell+ swap
! 183: r> loop
! 184: drop 2drop ;
! 185:
! 186: : notb&and \ w1 w2 -- w3 )
! 187: -1 xor and ;
! 188:
! 189: : subset? \ set1 set2 -- f )
! 190: \ returns true if every member of set1 is in set2 )
! 191: ['] notb&and binary-set-test? ;
! 192:
! 193: : disjoint? \ set1 set2 -- f )
! 194: \ returns true if set1 and set2 heve no common members )
! 195: ['] and binary-set-test? ;
! 196:
! 197: : apply-to-members \ set [ u -- ] -- )
! 198: \ executes [ u -- ] for every member of set )
! 199: cells/set @ bits/cell * 0 do
! 200: over i member? if
! 201: i over execute
! 202: endif
! 203: loop
! 204: 2drop ;
! 205:
! 206: : union \ set1 set2 -- set )
! 207: \ just a little more space-efficient )
! 208: 2dup subset? if
! 209: swap drop
! 210: else 2dup swap subset? if
! 211: drop
! 212: else
! 213: union1
! 214: endif endif ;
! 215:
! 216:
! 217: \ tests )
! 218: variable test-vector ' abort test-vector !
! 219: \ here you should store the execution address of a word ( set -- f )
! 220: \ that returns true if the token of the current symbol is in set )
! 221:
! 222: : compile-test \ set -- )
! 223: postpone literal
! 224: test-vector @ compile, ;
! 225:
! 226:
! 227: \ context management )
! 228: 500 stack context-stack
! 229: \ this stack holds the syntax-exprs currently being treated )
! 230: \ enlarge it, if your grammar is large and complex )
! 231: context-stack clear
! 232:
! 233: : this \ -- syntax-expr )
! 234: \ get current syntax-expr )
! 235: context-stack top ;
! 236:
! 237: : new-context \ syntax-expr -- )
! 238: context-stack push ;
! 239:
! 240: : old-context \ -- )
! 241: context-stack pop ;
! 242:
! 243:
! 244: \ structures )
! 245: : <builds-field \ n1 n2 -- n3 ) ( defining-word )
! 246: \ n1 is the offset of the field, n2 its length, n3 the offset of the
! 247: \ next field; creates a word that contains the offset )
! 248: create over , + ;
! 249:
! 250: 0 constant struct
! 251: \ initial offset
! 252:
! 253: : context-var \ use: < offset > size context-var name < offset2 > )
! 254: \ name returns the address of the offset field of "this" )
! 255: <builds-field \ n1 n2 -- n3 )
! 256: does> \ -- addr )
! 257: @ this + ;
! 258:
! 259: : context-const \ use: < offset > context-const name < offset2 > )
! 260: \ name returns the contents of the field of this at offset )
! 261: cell <builds-field \ n1 -- n2 )
! 262: does> \ -- n )
! 263: @ this + @ ;
! 264:
! 265:
! 266: \ syntax-exprs )
! 267: struct
! 268: aligned context-const methods
! 269: \ table of words applicable to the syntax-expr (a map)
! 270: 1 context-var mark-propagate \ used to ensure that "propagate" is
! 271: \ called at least once for each syntax-expr )
! 272: 1 context-var mark-pass2
! 273: \ make sure pass2 is called exactly once )
! 274: aligned cell context-var first-set
! 275: \ all tokens a nonempty path may begin with )
! 276: \ if it's equal to 0, the first-set has not been computed yet )
! 277: 1 context-var maybe-empty
! 278: \ true if the syntax-expr can derive eps )
! 279: aligned cell context-var follow-set
! 280: \ the tokens of the terminals that can follow the syntax-expr )
! 281: aligned 2 cells context-var source-location \ for error msgs )
! 282: constant syntax-expr \ length of a syntax-expr )
! 283:
! 284: : make-syntax-expr \ map -- syntax-expr )
! 285: \ allocate a syntax-expr and initialize it )
! 286: here swap , false c, false c,
! 287: align 0 , false c, align empty ,
! 288: \ source location !! implementation dependent )
! 289: \ if you use blocks, use:
! 290: \ blk @ >in @ 2,
! 291: \ the following is just a dummy
! 292: 0 loadline @ 2,
! 293: ;
! 294:
! 295:
! 296: \ warnings and errors )
! 297: : .in \ -- )
! 298: \ !! implementation dependent )
! 299: \ prints the info stored in source-location in a usable way )
! 300: \ prints where the error happened )
! 301: source-location 2@ ." line" . drop ." :" ;
! 302:
! 303:
! 304: : gray-error abort ;
! 305:
! 306: : internal-error
! 307: cr .in ." you found a bug" gray-error ;
! 308:
! 309: variable print-token ' . print-token !
! 310: \ contains execution address of a word < token -- > to print a token )
! 311:
! 312: : check-conflict \ set1 set2 -- )
! 313: \ print the intersection of set1 and set2 if it isn't empty )
! 314: 2dup disjoint? ?not? if
! 315: cr .in ." conflict:"
! 316: intersection print-token @ apply-to-members
! 317: else
! 318: 2drop
! 319: endif ;
! 320:
! 321:
! 322: \ methods and maps )
! 323: : method \ use: < offset > method name < offset2 > )
! 324: \ executes the word whose execution address is stored in the field
! 325: \ at offset of a table pointed to by the "methods" field of "this" )
! 326: cell <builds-field \ n1 -- n2 )
! 327: does>
! 328: @ methods + @ execute ;
! 329:
! 330: \ method table for syntax-exprs
! 331: struct
! 332: method compute-method
! 333: method propagate-method
! 334: method generate-method
! 335: method pass2-method
! 336: constant syntax-expr-methods
! 337:
! 338:
! 339: \ general routines )
! 340: : compute \ syntax-expr -- first-set maybe-empty )
! 341: \ compute the first-set and maybe-empty of a syntax-expr )
! 342: \ a bit of memoization is used here )
! 343: new-context
! 344: first-set @ 0= if
! 345: compute-method
! 346: maybe-empty c!
! 347: first-set !
! 348: endif
! 349: first-set @ maybe-empty c@
! 350: old-context ;
! 351:
! 352: : get-first \ syntax-expr -- first-set )
! 353: compute drop ;
! 354:
! 355: : check-cycle \ syntax-expr -- )
! 356: \ just check for left recursion )
! 357: compute 2drop ;
! 358:
! 359: : propagate \ follow-set syntax-expr -- )
! 360: \ add follow-set to the follow set of syntax-expr and its children )
! 361: new-context
! 362: dup follow-set @ subset? ?not? \ would everything stay the same
! 363: mark-propagate c@ ?not? or if \ and was propagate here already
! 364: true mark-propagate c! \ NO, do propagate
! 365: follow-set @ union dup follow-set !
! 366: propagate-method
! 367: else
! 368: drop
! 369: endif
! 370: old-context ;
! 371:
! 372: : generate \ syntax-expr -- )
! 373: \ this one gets things done )
! 374: new-context generate-method old-context ;
! 375:
! 376: : pass2 \ syntax-expr -- )
! 377: \ computes all necessary first sets, checks for left recursions
! 378: \ and conflicts and generates code for rules )
! 379: new-context
! 380: mark-pass2 c@ ?not? if
! 381: true mark-pass2 c!
! 382: this check-cycle
! 383: pass2-method
! 384: endif
! 385: old-context ;
! 386:
! 387:
! 388: \ main routine )
! 389: : parser \ syntax-expr -- )
! 390: \ use: syntax-expr parser xxx )
! 391: context-stack clear
! 392: empty over propagate
! 393: dup pass2
! 394: \ : should not be immediate
! 395: >r : r> generate postpone ; ;
! 396:
! 397:
! 398: \ eps - empty syntax-expr )
! 399: create eps-map
! 400: ', internal-error
! 401: ', drop
! 402: ', noop
! 403: ', noop
! 404:
! 405:
! 406: create eps1
! 407: \ the eps syntax-expr proper
! 408: eps-map make-syntax-expr
! 409: drop
! 410:
! 411:
! 412: : eps \ -- syntax-expr )
! 413: \ just adjusts eps1 and returns it
! 414: eps1 new-context
! 415: empty first-set ! ( empty changes due to max-member )
! 416: empty follow-set !
! 417: true maybe-empty c!
! 418: old-context
! 419: eps1 ;
! 420:
! 421:
! 422: \ terminals )
! 423: \ a terminal is a syntax-expr with an extra field )
! 424: syntax-expr
! 425: context-const check&next
! 426: \ contains address of a word < f -- > that checks
! 427: \ if f is true and reads the next terminal symbol )
! 428: constant terminal-syntax-expr
! 429:
! 430: : generate-terminal \ -- )
! 431: this get-first compile-test
! 432: check&next compile, ;
! 433:
! 434: create terminal-map
! 435: ', internal-error
! 436: ', drop
! 437: ', generate-terminal
! 438: ', noop
! 439:
! 440: : make-terminal \ first-set cfa -- syntax-expr )
! 441: terminal-map make-syntax-expr
! 442: new-context
! 443: ,
! 444: first-set !
! 445: this old-context ;
! 446:
! 447: : terminal \ first-set cfa -- )
! 448: create make-terminal drop ;
! 449:
! 450:
! 451: \ binary syntax-exprs )
! 452: syntax-expr
! 453: context-const operand1
! 454: context-const operand2
! 455: constant binary-syntax-expr
! 456:
! 457: : make-binary \ syntax-expr1 syntax-expr2 map -- syntax-expr )
! 458: make-syntax-expr rot , swap , ;
! 459:
! 460: : pass2-binary
! 461: operand1 pass2
! 462: operand2 pass2 ;
! 463:
! 464:
! 465: \ concatenations )
! 466: : compute-concatenation \ -- first maybe-empty )
! 467: operand1 compute dup if
! 468: drop
! 469: operand2 compute
! 470: >r union r>
! 471: endif ;
! 472:
! 473: : propagate-concatenation \ follow-set -- )
! 474: operand2 compute if
! 475: over union
! 476: endif \ follow follow1 )
! 477: operand1 propagate
! 478: operand2 propagate ;
! 479:
! 480: : generate-concatenation \ -- )
! 481: operand1 generate
! 482: operand2 generate ;
! 483:
! 484: create concatenation-map
! 485: ', compute-concatenation
! 486: ', propagate-concatenation
! 487: ', generate-concatenation
! 488: ', pass2-binary
! 489:
! 490: : concat \ syntax-expr1 syntax-expr2 -- syntax-expr )
! 491: concatenation-map make-binary ;
! 492: \ this is the actual concatenation operator )
! 493: \ but for safety and readability the parenthesised notation )
! 494: \ is preferred )
! 495:
! 496:
! 497: \ alternatives )
! 498: : compute-alternative \ -- first maybe-empty )
! 499: operand1 compute
! 500: operand2 compute
! 501: rot 2dup and if
! 502: cr .in ." warning: two branches may be empty" endif
! 503: or >r union r> ;
! 504:
! 505: : propagate-alternative \ follow -- )
! 506: dup operand1 propagate
! 507: operand2 propagate ;
! 508:
! 509: : generate-alternative1 \ -- )
! 510: operand1 get-first compile-test
! 511: postpone if
! 512: operand1 generate
! 513: postpone else
! 514: operand2 generate
! 515: postpone endif ;
! 516:
! 517: : generate-alternative2 \ -- )
! 518: operand1 get-first compile-test postpone ?not?
! 519: operand2 get-first compile-test postpone and
! 520: postpone if
! 521: operand2 generate
! 522: postpone else
! 523: operand1 generate
! 524: postpone endif ;
! 525:
! 526: : generate-alternative \ -- )
! 527: operand1 compute if
! 528: generate-alternative2
! 529: else
! 530: generate-alternative1
! 531: endif
! 532: drop ;
! 533:
! 534: : pass2-alternative \ -- )
! 535: this compute if
! 536: follow-set @ check-conflict
! 537: else
! 538: drop
! 539: endif
! 540: operand1 get-first operand2 get-first check-conflict
! 541: pass2-binary ;
! 542:
! 543: create alternative-map
! 544: ', compute-alternative
! 545: ', propagate-alternative
! 546: ', generate-alternative
! 547: ', pass2-alternative
! 548:
! 549: : alt \ syntax-expr1 syntax-expr2 -- syntax-expr )
! 550: alternative-map make-binary ;
! 551: \ this is the actual alternative operator )
! 552: \ but for safety and readability the parenthesised notation )
! 553: \ is preferred )
! 554:
! 555:
! 556: \ unary syntax-exprs )
! 557: syntax-expr
! 558: context-const operand
! 559: constant unary-syntax-expr
! 560:
! 561: : make-unary \ syntax-expr1 map -- syntax-expr2 )
! 562: make-syntax-expr swap , ;
! 563:
! 564:
! 565: \ options and repetitions )
! 566: : pass2-option&repetition \ -- )
! 567: follow-set @ operand get-first check-conflict
! 568: operand pass2 ;
! 569:
! 570:
! 571: \ options )
! 572: : compute-option \ -- set f )
! 573: operand compute if
! 574: cr .in ." warning: unnessesary option" endif
! 575: true ;
! 576:
! 577: : propagate-option \ follow -- )
! 578: operand propagate ;
! 579:
! 580: : generate-option \ -- )
! 581: operand get-first compile-test
! 582: postpone if
! 583: operand generate
! 584: postpone endif ;
! 585:
! 586: create option-map
! 587: ', compute-option
! 588: ', propagate-option
! 589: ', generate-option
! 590: ', pass2-option&repetition
! 591:
! 592: : ?? \ syntax-expr1 -- syntax-expr2 )
! 593: option-map make-unary ;
! 594:
! 595:
! 596: \ repetitions )
! 597: : propagate-repetition \ follow-set -- )
! 598: operand get-first union operand propagate ;
! 599:
! 600:
! 601: \ *-repetitions )
! 602: : compute-*repetition \ -- set f )
! 603: operand compute if
! 604: cr .in ." warning: *repetition of optional term" endif
! 605: true ;
! 606:
! 607: : generate-*repetition \ -- )
! 608: postpone begin
! 609: operand get-first compile-test
! 610: postpone while
! 611: operand generate
! 612: postpone repeat ;
! 613:
! 614: create *repetition-map
! 615: ', compute-*repetition
! 616: ', propagate-repetition
! 617: ', generate-*repetition
! 618: ', pass2-option&repetition
! 619:
! 620: : ** \ syntax-expr1 -- syntax-expr2 )
! 621: *repetition-map make-unary ;
! 622:
! 623:
! 624: \ +-repetitions )
! 625: : compute-+repetition \ -- set f )
! 626: operand compute ;
! 627:
! 628: : generate-+repetition \ -- )
! 629: postpone begin
! 630: operand generate
! 631: operand get-first compile-test
! 632: postpone ?not? postpone until ;
! 633:
! 634: create +repetition-map
! 635: ', compute-+repetition
! 636: ', propagate-repetition
! 637: ', generate-+repetition
! 638: ', pass2-option&repetition
! 639:
! 640: : ++ \ syntax-expr1 -- syntax-expr2 )
! 641: +repetition-map make-unary ;
! 642:
! 643:
! 644: \ actions )
! 645: syntax-expr
! 646: context-const action
! 647: constant action-syntax-expr
! 648:
! 649: : generate-action \ syntax-expr -- )
! 650: action compile, ;
! 651:
! 652: create action-map
! 653: ', internal-error
! 654: ', drop
! 655: ', generate-action
! 656: ', noop
! 657:
! 658: : {{ \ -- syntax-expr addr colon-sys )
! 659: action-map make-syntax-expr
! 660: new-context
! 661: empty first-set !
! 662: true maybe-empty c!
! 663: this old-context
! 664: \ ?exec !csp )
! 665: here cell allot
! 666: :noname ;
! 667:
! 668: : }} \ syntax-expr addr colon-sys -- syntax-expr )
! 669: \ ?csp )
! 670: postpone ;
! 671: swap !
! 672: ; immediate
! 673:
! 674:
! 675: \ nonterminals )
! 676: syntax-expr
! 677: 1 context-var mark-compute
! 678: aligned cell context-var rule-body \ in forth left side of rule )
! 679: cell context-var exec \ cfa of code for rule )
! 680: constant nt-syntax-expr
! 681:
! 682: : get-body \ -- syntax-expr )
! 683: \ get the body of the rule for the nt in "this" )
! 684: rule-body @ if
! 685: rule-body @
! 686: else
! 687: cr .in ." no rule for nonterminal" gray-error
! 688: endif ;
! 689:
! 690: : compute-nt \ -- set f )
! 691: mark-compute c@ if
! 692: cr .in ." left recursion" gray-error
! 693: else
! 694: true mark-compute c!
! 695: get-body compute
! 696: endif ;
! 697:
! 698: : propagate-nt \ follow-set -- )
! 699: get-body propagate ;
! 700:
! 701: : code-nt \ -- )
! 702: \ generates the code for a rule )
! 703: :noname
! 704: get-body generate
! 705: postpone ;
! 706: exec ! ;
! 707:
! 708: : generate-nt \ -- )
! 709: \ generates a call to the code for the rule )
! 710: \ since the code needs not be generated yet, an indirect call is used )
! 711: exec postpone literal
! 712: postpone @
! 713: postpone execute ;
! 714:
! 715: : pass2-nt \ -- )
! 716: \ apart from the usual duties, this pass2 also has to code-nt )
! 717: get-body pass2
! 718: code-nt ;
! 719:
! 720: create nt-map
! 721: ', compute-nt
! 722: ', propagate-nt
! 723: ', generate-nt
! 724: ', pass2-nt
! 725:
! 726: : make-nt \ syntax-expr -- nt )
! 727: nt-map make-syntax-expr
! 728: false c, align swap , 0 , ;
! 729:
! 730: : <- \ use: syntax-expr <- xxx )
! 731: \ xxx: -- syntax-expr )
! 732: create make-nt drop ;
! 733:
! 734: : nonterminal \ use: nonterminal xxx )
! 735: 0 <- ; \ forward declaration )
! 736:
! 737: : rule \ syntax-expr nt -- )
! 738: \ makes a rule )
! 739: new-context
! 740: rule-body @ if
! 741: .in ." multiple rules for nonterminal" gray-error endif
! 742: rule-body !
! 743: old-context ;
! 744:
! 745:
! 746: \ syntactic sugar )
! 747: : reduce \ 0 x1 ... [x2 x3 -- x4] -- x )
! 748: \ e.g. 0 5 6 7 ' + reduce = 5 6 7 + + = 18 )
! 749: >r dup 0= if
! 750: ." no operand" abort
! 751: endif
! 752: begin
! 753: over 0= ?not? while
! 754: r@ execute
! 755: repeat \ 0 x )
! 756: swap drop r> drop ;
! 757:
! 758: 7 constant concatenation-id
! 759: : (- \ -- n 0 )
! 760: concatenation-id 0 ;
! 761: : -) \ n 0 syntax-expr1 syntax-expr2 .. -- syntax-expr )
! 762: ['] concat reduce
! 763: swap concatenation-id ?pairs ;
! 764:
! 765: 8 constant alternative-id
! 766: : (| \ -- n 0 )
! 767: alternative-id 0 ;
! 768: : |) \ n 0 syntax-expr1 syntax-expr2 .. -- syntax-expr )
! 769: ['] alt reduce
! 770: swap alternative-id ?pairs ;
! 771:
! 772: : (( (| (- ;
! 773: : )) -) |) ;
! 774: : || -) (- ;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>