Schreiben Sie ein Parsewort INFIX:, welches binäre Operationen in Infix-Notation erlaubt. Beispiel INFIX: 2 + 3 wird in 2 3 + umgewandelt. SYNTAX: INFIX: scan-word parsed scan-word scan-word swap [ parsed ] dip parsed ; { 5 } [ INFIX: 2 + 3 ] unit-test { [ 2 3 + ] } [ [ INFIX: 2 + 3 ] ] unit-test { t } [ INFIX: t and t ] unit-test Schreiben Sie ein Parsewort BEGINNUM ... ENDNUM welches die Anzahl der Elemente zwischen BEGINNUM und dem Delimiter ENDNUM zählt. Beispiel: BEGINNUM 1 1 1 1 1 1 1 ENDNUM ergibt 7. : ENDNUM ( -- ) ; delimiter SYNTAX: BEGINNUM \ ENDNUM parse-until length parsed ; { 7 } [ BEGINNUM 1 1 1 1 1 1 1 ENDNUM ] unit-test { 0 } [ BEGINNUM ENDNUM ] unit-test { 2 } [ BEGINNUM [ 1 2 ] "hello" ENDNUM ] unit-test Schreiben Sie ein Parsewort PUT:, welches eine Quotation, einen Pfeil nach links oder rechts und noch eine Quotation erwartet. Zeigt der Pfeil nach links, wird die zweite Quotation als letztes Element der ersten Quotation angehängt, zeigt er nach rechts, wird die erste Quotation als erstes Element in die zweite Quotation eingefügt. Beispiel: PUT: [ 1 2 ] -> [ 3 4 ] ergibt [ [ 1 2 ] 3 4 ] und [ 1 2 ] <- [ 3 4 ] ergibt [ 1 2 [ 3 4 ] ] SYNTAX: PUT: scan "[" assert= parse-quotation scan scan "[" assert= parse-quotation swap dup "->" = [ drop swap prefix ] [ "<-" assert= suffix ] if parsed ; { [ [ ] ] } [ PUT: [ ] -> [ ] ] unit-test { [ [ ] ] } [ PUT: [ ] <- [ ] ] unit-test { [ [ 1 2 ] 3 4 ] } [ PUT: [ 1 2 ] -> [ 3 4 ] ] unit-test { [ 1 2 [ 3 4 ] ] } [ PUT: [ 1 2 ] <- [ 3 4 ] ] unit-test Schreiben Sie ein Parsewort [++, welches eine Quotation die Zahlen enthält in eine Quotation umwandelt, in der jede Zahl um 1 erhöht ist. Innerhalb von [++ ... ] können verschachtelt Quotations enthalten sein. Beispiel: [++ 1 [ 2 3 [ 4 ] ] ] wird zur Parsezeit umgeschrieben in [ 2 [ 3 4 [ 5 ] ] ]. Um den Fehlerfall, in dem die Quotation andere Objekte als Zahlen enthält, müssen Sie sich nicht kümmern. Hinweis: Schauen Sie sich das Wort map an. : incq ( q1 -- q2 ) [ dup quotation? [ incq ] [ 1 + ] if ] map ; SYNTAX: [++ parse-quotation parsed incq ; { [ ] } [ [++ ] ] unit-test { [ 2 ] } [ [++ 1 ] ] unit-test { [ 2 3 [ 4 [ 5 ] ] 6 ] } [ [++ 1 2 [ 3 [ 4 ] ] 5 ] ] unit-test Schreiben Sie ein Parsewort DO, welches List Comprehensions in Factor umsetzt. Beispiel: DO [ dup * ] FOR [ 1 2 3 4 5 ] WHERE [ 4 < ] Die erste Quotation wird auf alle Elemente der zweiten Quotation angewendet, für die die Anwendung der dritten Quotation nicht f ist. Im obigen Fall ist das Ergebnis [ 1 4 9 ]. SYNTAX: DO scan "[" assert= parse-quotation scan "FOR" assert= scan "[" assert= parse-quotation scan "WHERE" assert= scan "[" assert= parse-quotation filter swap map parsed ; inline { [ 1 4 9 ] } [ DO [ dup * ] FOR [ 1 2 3 4 5 ] WHERE [ 4 < ] ] unit-test { [ 6 7 ] } [ DO [ 1 + ] FOR [ 1 2 3 4 5 6 ] WHERE [ 4 > ] ] unit-test { [ 3 4 ] } [ DO [ ] FOR [ 1 2 3 4 5 6 ] WHERE [ dup 2 > swap 5 < and ] ] unit-test { [ 1 16 ] } [ DO [ dup * ] FOR [ 1 "2" [ 3 ] 4 ] WHERE [ number? ] ] unit-test Schreiben Sie ein Parsewort RULE: welches Zustandsübergänge für Automaten beschreibt. Beispiel: RULE: A x => B Diese Regel beschreibt den Übergang vom Zustand A in Zustand B, wenn x gelesen wird. Sie wird dargestellt als: [ [ A x ] [ B ] ] Schreiben Sie nun ein Parse-Wort RULES, welches ein Menge von Regeln entgegennimmt: SYMBOLS: A B x y RULES: RULE: A x => B RULE: B y => A END Das Ergebnis soll eine Regelvektor sein: V{ [ [ A x ] [ B ] ] [ [ B y ] [ A ] ] } : END ( -- ) ; delimiter SYNTAX: RULE: [ ] [ ] scan-word prefix scan-word suffix scan "=>" assert= [ ] scan-word prefix [ prefix ] dip suffix parsed ; SYNTAX: RULES: \ END parse-until parsed ; SYMBOLS: A B x y ; { [ [ A x ] [ B ] ] } [ RULE: A x => B ] unit-test { V{ } } [ RULES: ; ] unit-test { V{ [ [ A x ] [ B ] ] [ [ B y ] [ A ] ] } } [ SYMBOLS: A B C x y ; RULES: RULE: A x => B RULE: B y => A ; ] unit-test Definieren Sie nun Parsewörter für eine Automatendefinition in folgendem Stil: AUTOMATON: STATES: A B ; ALPHABET: x y ; RULES: RULE: A x => B RULE: B y => A END START: A FINAL: B ; END : END ( -- ) ; delimiter SYNTAX: RULE: [ ] [ ] scan-word prefix scan-word suffix scan "=>" assert= [ ] scan-word prefix [ prefix ] dip suffix parsed ; SYNTAX: RULES: \ END parse-until parsed ; SYNTAX: STATES: \ ; parse-until parsed ; SYNTAX: ALPHABET: \ ; parse-until parsed ; SYNTAX: START: scan-word [ ] swap prefix parsed ; SYNTAX: FINAL: \ ; parse-until parsed ; SYNTAX: AUTOMATON: \ END parse-until parsed ; SYMBOLS: A B x y ; [ V{ V{ A B } V{ x y } V{ [ [ A x ] [ B ] ] [ [ B y ] [ A ] ] } [ A ] V{ B } } ] [ AUTOMATON: STATES: A B ; ALPHABET: x y ; RULES: RULE: A x => B RULE: B y => A END START: A FINAL: B ; END ] unit-test Definieren Sie Fried Quotations, die äquivalent zu folgenden Programmen sind: [ 1 + ] curry [ + ] 2curry [ _ + ] [ _ _ + ] Definieren Sie eine Fried Quotation, die folgende Fried Quotation vereinfacht: [ 1 _ call 4 ] [ 1 @ 4 ]