Compiler/lexical analyzer: Difference between revisions

Content added Content deleted
m (minor edits)
m (Fix a bug in make-this-or-that-handler and use lisp keywords instead of obscure symbols.)
Line 1,677: Line 1,677:
do (setf may-end (char= ch #\*))
do (setf may-end (char= ch #\*))
finally (return (read stream t nil t))))
finally (return (read stream t nil t))))
(t (make-token :name '|Op_divide| :line (line-of stream) :column (column-of stream)))))
(t (make-token :name :op-divide :line (line-of stream) :column (column-of stream)))))


(defun make-constant-handler (token-name)
(defun make-constant-handler (token-name)
Line 1,693: Line 1,693:
(read-char stream nil nil t)
(read-char stream nil nil t)
(make-token :name then :line line :column column))
(make-token :name then :line line :column column))
((make-token :name else :line line :column column))
(else
(t (lexer-error "Unrecognized character '~A'" next))))))
(make-token :name else :line line :column column))
(t
(lexer-error "Unrecognized character '~A'" next))))))


(defun identifier? (symbol)
(defun identifier? (symbol)
Line 1,709: Line 1,711:
(defun id->keyword (id line column)
(defun id->keyword (id line column)
(case id
(case id
(|if| (make-token :name '|Keyword_if| :line line :column column))
(|if| (make-token :name :keyword-if :line line :column column))
(|else| (make-token :name '|Keyword_else| :line line :column column))
(|else| (make-token :name :keyword-else :line line :column column))
(|while| (make-token :name '|Keyword_while| :line line :column column))
(|while| (make-token :name :keyword-while :line line :column column))
(|print| (make-token :name '|Keyword_print| :line line :column column))
(|print| (make-token :name :keyword-print :line line :column column))
(|putc| (make-token :name '|Keyword_putc| :line line :column column))
(|putc| (make-token :name :keyword-putc :line line :column column))
(t nil)))
(t nil)))


Line 1,725: Line 1,727:
(if (identifier? obj)
(if (identifier? obj)
(or (id->keyword obj line column)
(or (id->keyword obj line column)
(make-token :name '|Identifier| :value obj :line line :column column))
(make-token :name :identifier :value obj :line line :column column))
(lexer-error "Invalid identifier name: ~A" obj))))))
(lexer-error "Invalid identifier name: ~A" obj))))))


Line 1,736: Line 1,738:
(let ((obj (read stream t nil t)))
(let ((obj (read stream t nil t)))
(if (integerp obj)
(if (integerp obj)
(make-token :name '|Integer| :value obj :line line :column column)
(make-token :name :integer :value obj :line line :column column)
(lexer-error "Invalid integer: ~A" obj))))))
(lexer-error "Invalid integer: ~A" obj))))))


Line 1,754: Line 1,756:
(t ch))))
(t ch))))
(if (char= #\' (read-char stream t nil t))
(if (char= #\' (read-char stream t nil t))
(make-token :name '|Integer| :value (char-code parsed) :line line :column column)
(make-token :name :integer :value (char-code parsed) :line line :column column)
(lexer-error "Only one character is allowed in character literal"))))
(lexer-error "Only one character is allowed in character literal"))))


Line 1,773: Line 1,775:
(t ch)))
(t ch)))
(vector-push-extend ch result)
(vector-push-extend ch result)
finally (return (make-token :name '|String| :value result :line line :column column))))
finally (return (make-token :name :string :value result :line line :column column))))


(defun make-lexer-readtable ()
(defun make-lexer-readtable ()
Line 1,783: Line 1,785:


;; operators
;; operators
(set-macro-character #\* (make-constant-handler '|Op_multiply|))
(set-macro-character #\* (make-constant-handler :op-multiply))
(set-macro-character #\/ #'handle-divide-or-comment)
(set-macro-character #\/ #'handle-divide-or-comment)
(set-macro-character #\% (make-constant-handler '|Op_mod|))
(set-macro-character #\% (make-constant-handler :op-mod))
(set-macro-character #\+ (make-constant-handler '|Op_add|))
(set-macro-character #\+ (make-constant-handler :op-add))
(set-macro-character #\- (make-constant-handler '|Op_subtract|))
(set-macro-character #\- (make-constant-handler :op-subtract))
(set-macro-character #\< (make-this-or-that-handler #\= '|Op_lessequal| '|Op_less|))
(set-macro-character #\< (make-this-or-that-handler #\= :op-lessequal :op-less))
(set-macro-character #\> (make-this-or-that-handler #\= '|Op_greaterequal| '|Op_greater|))
(set-macro-character #\> (make-this-or-that-handler #\= :op-greaterequal :op-greater))
(set-macro-character #\= (make-this-or-that-handler #\= '|Op_equal| '|Op_assign|))
(set-macro-character #\= (make-this-or-that-handler #\= :op-equal :op-assign))
(set-macro-character #\! (make-this-or-that-handler #\= '|Op_notequal| '|Op_not|))
(set-macro-character #\! (make-this-or-that-handler #\= :op-notequal :op-not))
(set-macro-character #\& (make-this-or-that-handler #\& '|Op_and|))
(set-macro-character #\& (make-this-or-that-handler #\& :op-and))
(set-macro-character #\| (make-this-or-that-handler #\| '|Op_or|))
(set-macro-character #\| (make-this-or-that-handler #\| :op-or))


;; symbols
;; symbols
(set-macro-character #\( (make-constant-handler '|LeftParen|))
(set-macro-character #\( (make-constant-handler :leftparen))
(set-macro-character #\) (make-constant-handler '|RightParen|))
(set-macro-character #\) (make-constant-handler :rightparen))
(set-macro-character #\{ (make-constant-handler '|LeftBrace|))
(set-macro-character #\{ (make-constant-handler :leftbrace))
(set-macro-character #\} (make-constant-handler '|RightBrace|))
(set-macro-character #\} (make-constant-handler :rightbrace))
(set-macro-character #\; (make-constant-handler '|Semicolon|))
(set-macro-character #\; (make-constant-handler :semicolon))
(set-macro-character #\, (make-constant-handler '|Comma|))
(set-macro-character #\, (make-constant-handler :comma))


;; identifiers & keywords
;; identifiers & keywords
Line 1,830: Line 1,832:
(token-line token) (token-column token) (token-name token) (token-value token))
(token-line token) (token-column token) (token-name token) (token-value token))
finally (format t "~5D ~5D ~15A~%"
finally (format t "~5D ~5D ~15A~%"
(line-of stream) (column-of stream) '|End_of_input|)
(line-of stream) (column-of stream) :end-of-input)
(close stream))))
(close stream))))


Line 1,845: Line 1,847:
(if file
(if file
(lex file)
(lex file)
(error "File must be specified"))))
(error "File must be specified"))))</lang>
</lang>
{{out|case=test case 3}}
{{out|case=test case 3}}
<pre> 5 16 Keyword_print
<pre> 5 16 KEYWORD-PRINT
5 40 Op_subtract
5 40 OP-SUBTRACT
6 16 Keyword_putc
6 16 KEYWORD-PUTC
6 40 Op_less
6 40 OP-LESS
7 16 Keyword_if
7 16 KEYWORD-IF
7 40 Op_greater
7 40 OP-GREATER
8 16 Keyword_else
8 16 KEYWORD-ELSE
8 40 Op_lessequal
8 40 OP-LESSEQUAL
9 16 Keyword_while
9 16 KEYWORD-WHILE
9 40 Op_greaterequal
9 40 OP-GREATEREQUAL
10 16 LeftBrace
10 16 LEFTBRACE
10 40 Op_equal
10 40 OP-EQUAL
11 16 RightBrace
11 16 RIGHTBRACE
11 40 Op_notequal
11 40 OP-NOTEQUAL
12 16 LeftParen
12 16 LEFTPAREN
12 40 Op_and
12 40 OP-AND
13 16 RightParen
13 16 RIGHTPAREN
13 40 Op_or
13 40 OP-OR
14 16 Op_subtract
14 16 OP-SUBTRACT
14 40 Semicolon
14 40 SEMICOLON
15 16 Op_not
15 16 OP-NOT
15 40 Comma
15 40 COMMA
16 16 Op_multiply
16 16 OP-MULTIPLY
16 40 Op_assign
16 40 OP-ASSIGN
17 16 Op_divide
17 16 OP-DIVIDE
17 40 Integer 42
17 40 INTEGER 42
18 16 Op_mod
18 16 OP-MOD
18 40 String "String literal"
18 40 STRING "String literal"
19 16 Op_add
19 16 OP-ADD
19 40 Identifier variable_name
19 40 IDENTIFIER variable_name
20 26 Integer 10
20 26 INTEGER 10
21 26 Integer 92
21 26 INTEGER 92
22 26 Integer 32
22 26 INTEGER 32
23 1 End_of_input </pre>
23 1 END-OF-INPUT </pre>


=={{header|Euphoria}}==
=={{header|Euphoria}}==