lexer.fs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. \ lexer.fs Lexical Analyzer, RosettaCode Compiler Task 20170413
  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. CREATE COLUMN# 0 ,
  6. CREATE LINE# 1 ,
  7. : NEWLINE? ( c -- t|f) DUP 10 = SWAP 13 = OR ;
  8. : +IN ( c --)
  9. 1 SWAP NEWLINE?
  10. IF 0 COLUMN# ! LINE# ELSE COLUMN# THEN
  11. +! 0 BUF ! ;
  12. : PEEK BUF @ 0= IF STDIN KEY-FILE BUF ! THEN BUF @ ;
  13. : GETC PEEK DUP +IN ;
  14. : SKIP GETC DROP ;
  15. : .LOCATION 7 .R 4 .R SPACE ;
  16. : WHERE COLUMN# @ LINE# @ ;
  17. : .WHERE WHERE .LOCATION ;
  18. : .WHERE+ WHERE SWAP 1+ SWAP .LOCATION ;
  19. : U. 0 <# #S #> TYPE ;
  20. : EXPECT GETC OVER OVER =
  21. IF 2DROP
  22. ELSE CR ." stdin:" LINE# @ U. ." :" COLUMN# @ U. ." : "
  23. ." unexpected `" EMIT ." ', expecting `" EMIT ." '" CR
  24. BYE
  25. THEN ;
  26. : EQ PEEK [CHAR] = = IF SKIP 2SWAP THEN
  27. ." Op_" TYPE CR 2DROP ;
  28. CREATE ESC 4 C, CHAR $ C, CHAR $ C, CHAR \ C, 0 C,
  29. : ?ESC? CR ." Unknown escape sequence `\" EMIT ." '" CR BYE ;
  30. : >ESC ESC 4 + C! ESC ;
  31. : $$\n 10 ;
  32. : $$\\ [CHAR] \ ;
  33. : ESCAPE DUP >ESC FIND IF NIP EXECUTE ELSE DROP ?ESC? THEN ;
  34. : ?ESCAPE DUP [CHAR] \ = IF DROP GETC ESCAPE THEN ;
  35. : ?EOF DUP 4 = IF CR ." End-of-file in string" CR BYE THEN ;
  36. : ?EOL DUP NEWLINE?
  37. IF CR ." End-of-line in string" CR BYE THEN ;
  38. : STRING PAD
  39. BEGIN GETC ?EOF ?EOL DUP [CHAR] " <>
  40. WHILE OVER C! CHAR+
  41. REPEAT DROP PAD TUCK - ;
  42. : "TYPE" [CHAR] " EMIT TYPE [CHAR] " EMIT ;
  43. CREATE TOKEN 4 C, CHAR $ C, CHAR $ C, 0 C, 0 C,
  44. : >HEX DUP 9 > IF 7 + THEN [CHAR] 0 + ;
  45. : HI! $F0 AND 2/ 2/ 2/ 2/ >HEX TOKEN 3 + C! ;
  46. : LO! $0F AND >HEX TOKEN 4 + C! ;
  47. : >TOKEN DUP HI! LO! TOKEN ;
  48. : ?EOF DUP 4 = IF CR ." End-of-file in comment" CR BYE THEN ;
  49. : $$2F PEEK [CHAR] * =
  50. IF SKIP
  51. BEGIN
  52. GETC ?EOF [CHAR] * =
  53. PEEK [CHAR] / = AND
  54. UNTIL SKIP
  55. ELSE .WHERE ." Op_divide" CR THEN ;
  56. : $$22 .WHERE ." String " STRING "TYPE" CR ;
  57. : $$27 .WHERE GETC ?ESCAPE ." Integer " . [CHAR] ' EXPECT CR ;
  58. : $$04 .WHERE ." End_of_input" CR BYE ;
  59. : $$2D .WHERE ." Op_subtract" CR ;
  60. : $$2B .WHERE ." Op_add" CR ;
  61. : $$25 .WHERE ." Op_mod" CR ;
  62. : $$2A .WHERE ." Op_multiply" CR ;
  63. : $$7B .WHERE ." LeftBrace" CR ;
  64. : $$7D .WHERE ." RightBrace" CR ;
  65. : $$2C .WHERE ." Comma" CR ;
  66. : $$29 .WHERE ." RightParen" CR ;
  67. : $$28 .WHERE ." LeftParen" CR ;
  68. : $$3B .WHERE ." Semicolon" CR ;
  69. : $$3D .WHERE s" equal" s" assign" EQ ;
  70. : $$21 .WHERE s" notequal" s" not" EQ ;
  71. : $$3C .WHERE s" lessequal" s" less" EQ ;
  72. : $$3E .WHERE s" greaterequal" s" greater" EQ ;
  73. : $$26 .WHERE [CHAR] & EXPECT ." Op_and" CR ;
  74. : $$7C .WHERE [CHAR] | EXPECT ." Op_or" CR ;
  75. : $$20 ; \ space
  76. CREATE KEYWORD 0 C, CHAR $ C, CHAR $ C, 5 CHARS ALLOT
  77. : >KEYWORD DUP 2 + KEYWORD C!
  78. KEYWORD 3 + SWAP CMOVE KEYWORD ;
  79. : FIND-KW DUP 5 <=
  80. IF 2DUP >KEYWORD FIND
  81. IF TRUE 2SWAP 2DROP ELSE DROP FALSE THEN
  82. ELSE FALSE THEN ;
  83. : $$if ." Keyword_if" ;
  84. : $$else ." Keyword_else" ;
  85. : $$while ." Keyword_while" ;
  86. : $$print ." Keyword_print" ;
  87. : $$putc ." Keyword_putc" ;
  88. : DIGIT? 48 58 WITHIN ;
  89. : ALPHA? DUP 95 = SWAP \ underscore?
  90. DUP 97 123 WITHIN SWAP \ lower?
  91. 65 91 WITHIN OR OR ; \ upper?
  92. : ALNUM? DUP DIGIT? SWAP ALPHA? OR ;
  93. : INTEGER 0
  94. BEGIN PEEK DIGIT?
  95. WHILE GETC [CHAR] 0 - SWAP 10 * +
  96. REPEAT ;
  97. : ?INTEGER? CR ." Invalid number" CR BYE ;
  98. : ?INTEGER PEEK ALPHA? IF ?INTEGER? THEN ;
  99. : DIGIT .WHERE+ ." Integer " INTEGER ?INTEGER . CR ;
  100. : NAME PAD
  101. BEGIN PEEK ALNUM?
  102. WHILE GETC OVER C! CHAR+
  103. REPEAT PAD TUCK - ;
  104. : IDENT ." Identifier " TYPE ;
  105. : ALPHA .WHERE+ NAME FIND-KW
  106. IF EXECUTE ELSE IDENT THEN CR ;
  107. : ?CHAR? CR ." Character '" EMIT ." ' not recognized" CR BYE ;
  108. : SPACE? DUP BL = SWAP 9 14 WITHIN OR ;
  109. : SKIP-SPACE BEGIN PEEK SPACE? WHILE SKIP REPEAT ;
  110. : CONSUME
  111. SKIP-SPACE
  112. PEEK DIGIT? IF DIGIT ELSE
  113. PEEK ALPHA? IF ALPHA ELSE
  114. PEEK >TOKEN FIND
  115. IF SKIP EXECUTE ELSE GETC ?CHAR? BYE THEN
  116. THEN THEN ;
  117. : TOKENIZE BEGIN CONSUME AGAIN ;
  118. :NONAME DEFERS 'COLD TOKENIZE ; IS 'COLD