parser.fs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. \ parser.fs Syntax Analyzer, RosettaCode Compiler Task 20170418
  2. \ Copyright 2017, Eric Bavier <bavier@member.fsf.org>
  3. \ This is Free Software licensed under the GPLv3, or any later
  4. CREATE BUF 0 , \ single-character look-ahead buffer
  5. : PEEK BUF @ 0= IF KEY BUF ! THEN BUF @ ;
  6. : GETC PEEK 0 BUF ! ;
  7. : SPACE? DUP BL = SWAP 9 14 WITHIN OR ;
  8. : >SPACE BEGIN PEEK SPACE? WHILE GETC DROP REPEAT ;
  9. : DIGIT? 48 58 WITHIN ;
  10. : GETINT >SPACE 0
  11. BEGIN PEEK DIGIT?
  12. WHILE GETC [CHAR] 0 - SWAP 10 * +
  13. REPEAT ;
  14. : GETNAM >SPACE PAD 1+
  15. BEGIN PEEK SPACE? INVERT
  16. WHILE GETC OVER C! CHAR+
  17. REPEAT PAD TUCK - 1- PAD C! ;
  18. : GETSTR >SPACE PAD 1+ GETC DROP \ skip leading "
  19. BEGIN GETC DUP [CHAR] " <>
  20. WHILE OVER C! CHAR+
  21. REPEAT DROP PAD TUCK - 1- PAD C! ;
  22. : INTERN ( c-addr -- c-addr)
  23. HERE TUCK OVER C@ CHAR+ DUP ALLOT CMOVE ;
  24. CREATE #TK 0 ,
  25. : TK: CREATE #TK @ , 1 #TK +! DOES> @ ;
  26. TK: Op_subtract TK: Op_add
  27. TK: Op_mod TK: Op_multiply TK: Op_divide
  28. TK: Op_equal TK: Op_notequal
  29. TK: Op_less TK: Op_lessequal
  30. TK: Op_greater TK: Op_greaterequal
  31. TK: Op_and TK: Op_or
  32. CREATE #BIN #TK @ ,
  33. TK: End_of_input TK: Keyword_if TK: Keyword_else
  34. TK: Keyword_while TK: Keyword_print TK: Keyword_putc
  35. TK: String TK: Integer TK: Identifier
  36. TK: LeftParen TK: RightParen
  37. TK: LeftBrace TK: RightBrace
  38. TK: Semicolon TK: Comma
  39. TK: Op_assign TK: Op_not
  40. CREATE TOKEN 0 , 0 , 0 , 0 ,
  41. : TOKEN-TYPE TOKEN 2 CELLS + @ ;
  42. : TOKEN-VALUE TOKEN 3 CELLS + @ ;
  43. : GETTOK GETINT GETINT TOKEN 2!
  44. GETNAM FIND DROP EXECUTE
  45. DUP Integer = IF GETINT ELSE
  46. DUP String = IF GETSTR INTERN ELSE
  47. DUP Identifier = IF GETNAM INTERN ELSE
  48. 0 THEN THEN THEN
  49. TOKEN 3 CELLS + ! TOKEN 2 CELLS + ! ;
  50. : BINARY? TOKEN-TYPE [ #BIN @ ] LITERAL < ;
  51. \ Each AST Node is a sequence of cells in data space consisting
  52. \ of the execution token of a printing word, followed by that
  53. \ node's data. Each printing word receives the address of the
  54. \ node's data, and is responsible for printing that data
  55. \ appropriately.
  56. DEFER .NODE
  57. : .NULL DROP ." ;" CR ;
  58. CREATE $NULL ' .NULL ,
  59. : .IDENTIFIER ." Identifier " @ COUNT TYPE CR ;
  60. : $IDENTIFIER ( a-addr --) HERE SWAP ['] .IDENTIFIER , , ;
  61. : .INTEGER ." Integer " @ . CR ;
  62. : $INTEGER ( n --) HERE SWAP ['] .INTEGER , , ;
  63. : "TYPE" [CHAR] " EMIT TYPE [CHAR] " EMIT ;
  64. : .STRING ." String " @ COUNT "TYPE" CR ;
  65. : $STRING ( a-addr --) HERE SWAP ['] .STRING , , ;
  66. : .LEAF DUP @ COUNT TYPE CR CELL+ @ .NODE 0 .NULL ;
  67. : LEAF CREATE HERE CELL+ , BL WORD INTERN DROP
  68. DOES> HERE >R ['] .LEAF , @ , , R> ;
  69. LEAF $PRTC Prtc LEAF $PRTS Prts LEAF $PRTI Prti
  70. LEAF $NOT Not LEAF $NEGATE Negate
  71. : .BINARY DUP @ COUNT TYPE CR
  72. CELL+ DUP @ .NODE CELL+ @ .NODE ;
  73. : BINARY CREATE HERE CELL+ , BL WORD INTERN DROP
  74. DOES> HERE >R ['] .BINARY , @ , SWAP 2, R> ;
  75. BINARY $SEQUENCE Sequence BINARY $ASSIGN Assign
  76. BINARY $WHILE While BINARY $IF If
  77. BINARY $SUBTRACT Subtract BINARY $ADD Add
  78. BINARY $MOD Mod BINARY $MULTIPLY Multiply
  79. BINARY $DIVIDE Divide
  80. BINARY $LESS Less BINARY $LESSEQUAL LessEqual
  81. BINARY $GREATER Greater BINARY $GREATEREQUAL GreaterEqual
  82. BINARY $EQUAL Equal BINARY $NOTEQUAL NotEqual
  83. BINARY $AND And BINARY $OR Or
  84. CREATE PREC #BIN @ CELLS ALLOT PREC #BIN @ CELLS -1 FILL
  85. : PREC! CELLS PREC + ! ;
  86. 14 Op_not PREC! 13 Op_multiply PREC!
  87. 13 Op_divide PREC! 13 Op_mod PREC!
  88. 12 Op_add PREC! 12 Op_subtract PREC!
  89. 10 Op_less PREC! 10 Op_greater PREC!
  90. 10 Op_lessequal PREC! 10 Op_greaterequal PREC!
  91. 9 Op_equal PREC! 9 Op_notequal PREC!
  92. 5 Op_and PREC! 4 Op_or PREC!
  93. : PREC@ CELLS PREC + @ ;
  94. CREATE CONS #BIN @ CELLS ALLOT
  95. : CONS! CELLS CONS + ! ;
  96. ' $SUBTRACT Op_subtract CONS! ' $ADD Op_add CONS!
  97. ' $MULTIPLY Op_multiply CONS! ' $DIVIDE Op_divide CONS!
  98. ' $EQUAL Op_equal CONS! ' $NOTEQUAL Op_notequal CONS!
  99. ' $LESS Op_less CONS! ' $LESSEQUAL Op_lessequal CONS!
  100. ' $AND Op_and CONS! ' $OR Op_or CONS!
  101. ' $GREATER Op_greater CONS! ' $MOD Op_mod CONS!
  102. ' $GREATEREQUAL Op_greaterequal CONS!
  103. : TOK-CONS TOKEN-TYPE CELLS CONS + @ ;
  104. : (.NODE) DUP CELL+ SWAP @ EXECUTE ;
  105. ' (.NODE) IS .NODE
  106. : .- ( n --) 0 <# #S #> TYPE ;
  107. : EXPECT ( tk --) DUP TOKEN-TYPE <>
  108. IF CR ." stdin:" TOKEN 2@ SWAP .- ." :" .-
  109. ." : unexpected token, expecting " . CR BYE
  110. THEN DROP GETTOK ;
  111. : '(' LeftParen EXPECT ;
  112. : ')' RightParen EXPECT ;
  113. : '}' RightBrace EXPECT ;
  114. : ';' Semicolon EXPECT ;
  115. : ',' Comma EXPECT ;
  116. : '=' Op_assign EXPECT ;
  117. DEFER *EXPR DEFER EXPR DEFER STMT
  118. : PAREN-EXPR '(' EXPR ')' ;
  119. : PRIMARY
  120. TOKEN-TYPE LeftParen = IF PAREN-EXPR EXIT THEN
  121. TOKEN-TYPE Op_add = IF GETTOK 12 *EXPR EXIT THEN
  122. TOKEN-TYPE Op_subtract = IF GETTOK 14 *EXPR $NEGATE EXIT THEN
  123. TOKEN-TYPE Op_not = IF GETTOK 14 *EXPR $NOT EXIT THEN
  124. TOKEN-TYPE Identifier = IF TOKEN-VALUE $IDENTIFIER ELSE
  125. TOKEN-TYPE Integer = IF TOKEN-VALUE $INTEGER THEN THEN
  126. GETTOK ;
  127. : (*EXPR) ( n -- node)
  128. PRIMARY ( n node)
  129. BEGIN OVER TOKEN-TYPE PREC@ SWAP OVER <= BINARY? AND
  130. WHILE ( n node prec) 1+ TOK-CONS SWAP GETTOK *EXPR SWAP EXECUTE
  131. REPEAT ( n node prec) DROP NIP ( node) ;
  132. : (EXPR) 0 *EXPR ;
  133. : -)? TOKEN-TYPE RightParen <> ;
  134. : -}? TOKEN-TYPE RightBrace <> ;
  135. : (STMT)
  136. TOKEN-TYPE Semicolon = IF GETTOK STMT EXIT THEN
  137. TOKEN-TYPE Keyword_while =
  138. IF GETTOK PAREN-EXPR STMT $WHILE EXIT THEN
  139. TOKEN-TYPE Keyword_if =
  140. IF GETTOK PAREN-EXPR STMT
  141. TOKEN-TYPE Keyword_else = IF GETTOK STMT ELSE $NULL THEN
  142. $IF $IF EXIT
  143. THEN
  144. TOKEN-TYPE Keyword_putc =
  145. IF GETTOK PAREN-EXPR ';' $PRTC EXIT THEN
  146. TOKEN-TYPE Keyword_print =
  147. IF GETTOK '(' $NULL
  148. BEGIN TOKEN-TYPE String =
  149. IF TOKEN-VALUE $STRING $PRTS GETTOK
  150. ELSE EXPR $PRTI THEN $SEQUENCE -)?
  151. WHILE ',' REPEAT ')' ';' EXIT THEN
  152. TOKEN-TYPE Identifier =
  153. IF TOKEN-VALUE $IDENTIFIER GETTOK '=' EXPR ';' $ASSIGN
  154. EXIT THEN
  155. TOKEN-TYPE LeftBrace =
  156. IF $NULL GETTOK BEGIN -}? WHILE STMT $SEQUENCE REPEAT
  157. '}' EXIT THEN
  158. TOKEN-TYPE End_of_input = IF EXIT THEN EXPR ;
  159. ' (*EXPR) IS *EXPR ' (EXPR) IS EXPR ' (STMT) IS STMT
  160. : -EOI? TOKEN-TYPE End_of_input <> ;
  161. : PARSE $NULL GETTOK BEGIN -EOI? WHILE STMT $SEQUENCE REPEAT ;
  162. :NONAME DEFERS 'COLD PARSE .NODE BYE ; IS 'COLD