| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /* Copyright (C) 2019-2023 Hangzhou HSH Co. Ltd.
- * All right reserved.*/
- package com.craftinginterpreters.lox;
- import java.util.ArrayList;
- import java.util.List;
- import static com.craftinginterpreters.lox.TokenType.*;
- /**
- * @author simon
- * @date 2023-06-04 16:30
- * @desc
- */
- public class Scanner {
- private final String source;
- private final List<Token> tokens = new ArrayList<>();
- private int start = 0; // points to the first character in the lexeme being scanned
- private int current = 0; // points at the character currently being considered.
- private int line = 1;
- public Scanner(String source) {
- this.source = source;
- }
- public List<Token> scanTokens() {
- while (!isAtEnd()) {
- // We are at the beginning of the next lexeme.
- start = current;
- scanToken();
- }
- // add finish token to the end of list
- tokens.add(new Token(EOF, "", null, line));
- return tokens;
- }
- private void scanToken() {
- char c = advance();
- switch (c) {
- case '(' -> addToken(LEFT_PARAM);
- case ')' -> addToken(RIGHT_PARAM);
- case '{' -> addToken(LEFT_BRACE);
- case '}' -> addToken(RIGHT_BRACE);
- case ',' -> addToken(COMMA);
- case '.' -> addToken(DOT);
- case '-' -> addToken(MINUS);
- case '+' -> addToken(PLUS);
- case ';' -> addToken(SEMICOLON);
- case '*' -> addToken(STAR);
- // 两个字符 != == >= <=
- case '!' -> addToken(match('=') ? BANG_EQUAL : BANG);
- case '=' -> addToken(match('=') ? EQUAL_EQUAL : EQUAL);
- case '<' -> addToken(match('=') ? LESS_EQUAL : LESS);
- case '>' -> addToken(match('=') ? GRATER_EQUAL : GRATER);
- case '/' -> {
- if (match('/')) {
- // A comment goes until the end of the line.
- while (peek() != '\n' && !isAtEnd()) advance();
- } else {
- addToken(SLASH);
- }
- }
- // Ignore whitespace
- case ' ', '\r', '\t' -> {
- }
- case '\n' -> line++;
- default -> Lox.error(line, "Unexpected character: " + c);
- }
- }
- private char peek() {
- if (isAtEnd()) return '\0';
- return source.charAt(current);
- }
- private void addToken(TokenType type) {
- addToken(type, null);
- }
- private void addToken(TokenType type, Object literal) {
- String text = source.substring(start, current);
- tokens.add(new Token(type, text, literal, line));
- }
- /**
- * consumes the next character in the source file and returns it
- *
- * @return
- */
- private char advance() {
- return source.charAt(current++);
- }
- private boolean isAtEnd() {
- return current >= source.length();
- }
- private boolean match(char expected) {
- if (isAtEnd()) return false;
- if (source.charAt(current) != expected) return false;
- current++;
- return true;
- }
- }
|