123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- \ parser.fs Syntax Analyzer, RosettaCode Compiler Task 20170418
- \ Copyright 2017, Eric Bavier <bavier@member.fsf.org>
- \ This is Free Software licensed under the GPLv3, or any later
- CREATE BUF 0 , \ single-character look-ahead buffer
- : PEEK BUF @ 0= IF KEY BUF ! THEN BUF @ ;
- : GETC PEEK 0 BUF ! ;
- : SPACE? DUP BL = SWAP 9 14 WITHIN OR ;
- : >SPACE BEGIN PEEK SPACE? WHILE GETC DROP REPEAT ;
- : DIGIT? 48 58 WITHIN ;
- : GETINT >SPACE 0
- BEGIN PEEK DIGIT?
- WHILE GETC [CHAR] 0 - SWAP 10 * +
- REPEAT ;
- : GETNAM >SPACE PAD 1+
- BEGIN PEEK SPACE? INVERT
- WHILE GETC OVER C! CHAR+
- REPEAT PAD TUCK - 1- PAD C! ;
- : GETSTR >SPACE PAD 1+ GETC DROP \ skip leading "
- BEGIN GETC DUP [CHAR] " <>
- WHILE OVER C! CHAR+
- REPEAT DROP PAD TUCK - 1- PAD C! ;
- : INTERN ( c-addr -- c-addr)
- HERE TUCK OVER C@ CHAR+ DUP ALLOT CMOVE ;
- CREATE #TK 0 ,
- : TK: CREATE #TK @ , 1 #TK +! DOES> @ ;
- TK: Op_subtract TK: Op_add
- TK: Op_mod TK: Op_multiply TK: Op_divide
- TK: Op_equal TK: Op_notequal
- TK: Op_less TK: Op_lessequal
- TK: Op_greater TK: Op_greaterequal
- TK: Op_and TK: Op_or
- CREATE #BIN #TK @ ,
- TK: End_of_input TK: Keyword_if TK: Keyword_else
- TK: Keyword_while TK: Keyword_print TK: Keyword_putc
- TK: String TK: Integer TK: Identifier
- TK: LeftParen TK: RightParen
- TK: LeftBrace TK: RightBrace
- TK: Semicolon TK: Comma
- TK: Op_assign TK: Op_not
- CREATE TOKEN 0 , 0 , 0 , 0 ,
- : TOKEN-TYPE TOKEN 2 CELLS + @ ;
- : TOKEN-VALUE TOKEN 3 CELLS + @ ;
- : GETTOK GETINT GETINT TOKEN 2!
- GETNAM FIND DROP EXECUTE
- DUP Integer = IF GETINT ELSE
- DUP String = IF GETSTR INTERN ELSE
- DUP Identifier = IF GETNAM INTERN ELSE
- 0 THEN THEN THEN
- TOKEN 3 CELLS + ! TOKEN 2 CELLS + ! ;
- : BINARY? TOKEN-TYPE [ #BIN @ ] LITERAL < ;
- \ Each AST Node is a sequence of cells in data space consisting
- \ of the execution token of a printing word, followed by that
- \ node's data. Each printing word receives the address of the
- \ node's data, and is responsible for printing that data
- \ appropriately.
- DEFER .NODE
- : .NULL DROP ." ;" CR ;
- CREATE $NULL ' .NULL ,
- : .IDENTIFIER ." Identifier " @ COUNT TYPE CR ;
- : $IDENTIFIER ( a-addr --) HERE SWAP ['] .IDENTIFIER , , ;
- : .INTEGER ." Integer " @ . CR ;
- : $INTEGER ( n --) HERE SWAP ['] .INTEGER , , ;
- : "TYPE" [CHAR] " EMIT TYPE [CHAR] " EMIT ;
- : .STRING ." String " @ COUNT "TYPE" CR ;
- : $STRING ( a-addr --) HERE SWAP ['] .STRING , , ;
- : .LEAF DUP @ COUNT TYPE CR CELL+ @ .NODE 0 .NULL ;
- : LEAF CREATE HERE CELL+ , BL WORD INTERN DROP
- DOES> HERE >R ['] .LEAF , @ , , R> ;
- LEAF $PRTC Prtc LEAF $PRTS Prts LEAF $PRTI Prti
- LEAF $NOT Not LEAF $NEGATE Negate
- : .BINARY DUP @ COUNT TYPE CR
- CELL+ DUP @ .NODE CELL+ @ .NODE ;
- : BINARY CREATE HERE CELL+ , BL WORD INTERN DROP
- DOES> HERE >R ['] .BINARY , @ , SWAP 2, R> ;
- BINARY $SEQUENCE Sequence BINARY $ASSIGN Assign
- BINARY $WHILE While BINARY $IF If
- BINARY $SUBTRACT Subtract BINARY $ADD Add
- BINARY $MOD Mod BINARY $MULTIPLY Multiply
- BINARY $DIVIDE Divide
- BINARY $LESS Less BINARY $LESSEQUAL LessEqual
- BINARY $GREATER Greater BINARY $GREATEREQUAL GreaterEqual
- BINARY $EQUAL Equal BINARY $NOTEQUAL NotEqual
- BINARY $AND And BINARY $OR Or
- CREATE PREC #BIN @ CELLS ALLOT PREC #BIN @ CELLS -1 FILL
- : PREC! CELLS PREC + ! ;
- 14 Op_not PREC! 13 Op_multiply PREC!
- 13 Op_divide PREC! 13 Op_mod PREC!
- 12 Op_add PREC! 12 Op_subtract PREC!
- 10 Op_less PREC! 10 Op_greater PREC!
- 10 Op_lessequal PREC! 10 Op_greaterequal PREC!
- 9 Op_equal PREC! 9 Op_notequal PREC!
- 5 Op_and PREC! 4 Op_or PREC!
- : PREC@ CELLS PREC + @ ;
- CREATE CONS #BIN @ CELLS ALLOT
- : CONS! CELLS CONS + ! ;
- ' $SUBTRACT Op_subtract CONS! ' $ADD Op_add CONS!
- ' $MULTIPLY Op_multiply CONS! ' $DIVIDE Op_divide CONS!
- ' $EQUAL Op_equal CONS! ' $NOTEQUAL Op_notequal CONS!
- ' $LESS Op_less CONS! ' $LESSEQUAL Op_lessequal CONS!
- ' $AND Op_and CONS! ' $OR Op_or CONS!
- ' $GREATER Op_greater CONS! ' $MOD Op_mod CONS!
- ' $GREATEREQUAL Op_greaterequal CONS!
- : TOK-CONS TOKEN-TYPE CELLS CONS + @ ;
- : (.NODE) DUP CELL+ SWAP @ EXECUTE ;
- ' (.NODE) IS .NODE
- : .- ( n --) 0 <# #S #> TYPE ;
- : EXPECT ( tk --) DUP TOKEN-TYPE <>
- IF CR ." stdin:" TOKEN 2@ SWAP .- ." :" .-
- ." : unexpected token, expecting " . CR BYE
- THEN DROP GETTOK ;
- : '(' LeftParen EXPECT ;
- : ')' RightParen EXPECT ;
- : '}' RightBrace EXPECT ;
- : ';' Semicolon EXPECT ;
- : ',' Comma EXPECT ;
- : '=' Op_assign EXPECT ;
- DEFER *EXPR DEFER EXPR DEFER STMT
- : PAREN-EXPR '(' EXPR ')' ;
- : PRIMARY
- TOKEN-TYPE LeftParen = IF PAREN-EXPR EXIT THEN
- TOKEN-TYPE Op_add = IF GETTOK 12 *EXPR EXIT THEN
- TOKEN-TYPE Op_subtract = IF GETTOK 14 *EXPR $NEGATE EXIT THEN
- TOKEN-TYPE Op_not = IF GETTOK 14 *EXPR $NOT EXIT THEN
- TOKEN-TYPE Identifier = IF TOKEN-VALUE $IDENTIFIER ELSE
- TOKEN-TYPE Integer = IF TOKEN-VALUE $INTEGER THEN THEN
- GETTOK ;
- : (*EXPR) ( n -- node)
- PRIMARY ( n node)
- BEGIN OVER TOKEN-TYPE PREC@ SWAP OVER <= BINARY? AND
- WHILE ( n node prec) 1+ TOK-CONS SWAP GETTOK *EXPR SWAP EXECUTE
- REPEAT ( n node prec) DROP NIP ( node) ;
- : (EXPR) 0 *EXPR ;
- : -)? TOKEN-TYPE RightParen <> ;
- : -}? TOKEN-TYPE RightBrace <> ;
- : (STMT)
- TOKEN-TYPE Semicolon = IF GETTOK STMT EXIT THEN
- TOKEN-TYPE Keyword_while =
- IF GETTOK PAREN-EXPR STMT $WHILE EXIT THEN
- TOKEN-TYPE Keyword_if =
- IF GETTOK PAREN-EXPR STMT
- TOKEN-TYPE Keyword_else = IF GETTOK STMT ELSE $NULL THEN
- $IF $IF EXIT
- THEN
- TOKEN-TYPE Keyword_putc =
- IF GETTOK PAREN-EXPR ';' $PRTC EXIT THEN
- TOKEN-TYPE Keyword_print =
- IF GETTOK '(' $NULL
- BEGIN TOKEN-TYPE String =
- IF TOKEN-VALUE $STRING $PRTS GETTOK
- ELSE EXPR $PRTI THEN $SEQUENCE -)?
- WHILE ',' REPEAT ')' ';' EXIT THEN
- TOKEN-TYPE Identifier =
- IF TOKEN-VALUE $IDENTIFIER GETTOK '=' EXPR ';' $ASSIGN
- EXIT THEN
- TOKEN-TYPE LeftBrace =
- IF $NULL GETTOK BEGIN -}? WHILE STMT $SEQUENCE REPEAT
- '}' EXIT THEN
- TOKEN-TYPE End_of_input = IF EXIT THEN EXPR ;
- ' (*EXPR) IS *EXPR ' (EXPR) IS EXPR ' (STMT) IS STMT
- : -EOI? TOKEN-TYPE End_of_input <> ;
- : PARSE $NULL GETTOK BEGIN -EOI? WHILE STMT $SEQUENCE REPEAT ;
- :NONAME DEFERS 'COLD PARSE .NODE BYE ; IS 'COLD
|