Chapter 03

トークン

とが
とが
2021.11.28に更新
このチャプターの目次

字句解析のために,まずはトークンを定義する.

Token

まずは基底クラスから作る.

token.hpp
#include <memory>
#include <utility>

#include "pos.hpp"

namespace token {
    class Token {
    public:
        pos::Range pos;
        virtual ~Token();
        virtual void debug_print() const = 0;
    };
}
token.cpp
#include "token.hpp"

namespace token {
    Token::~Token() = default;
}

debug_print() はデバッグ出力用の関数だ.いずれ消す.

トークンは複数文字にわたるので,位置を表すのに pos::Range を使う.

Identifier

識別子は,正規表現 [A-Za-z_][A-Za-z_0-9]* に合致するものとする.

token.hpp
#include <string>

namespace token {
    class Identifier : public Token {
        std::string name;
    public:
        Identifier(std::string);
        void debug_print() const override;
    };
}
token.cpp
#include <iostream>

namespace token {
    Identifier::Identifier(std::string name): name(std::move(name)) {}
    void Identifier::debug_print() const {
        std::cout << "Identifier(" << name << ")" << std::endl;
    }
}

Integer

整数リテラルは [0-9]+

ゆくゆくは 0b 0o 0x で始まる 2,8,16 進リテラルや浮動小数点数リテラルも考えたいけど,今はやめておく.

整数なのにメンバ value の型は std::string.あとでこれを 32 ビット整数値に直すとき 2147483648 以上はエラーとするけれど,前に - が付いた -2147483648 は ok とする.

token.hpp
namespace token {
    class Integer : public Token {
        std::string value;
    public:
        Integer(std::string);
        void debug_print() const override;
    };
}
token.cpp
namespace token {
    Integer::Integer(std::string value): value(std::move(value)) {}
    void Integer::debug_print() const {
        std::cout << "Integer(" << value << ")" << std::endl;
    }
}

記号類

何があるといい?

  • 四則演算 + - * / %
  • ビット演算 ~ << >> & | ^
  • 比較 == != < > <= >=
  • 論理演算 && || !
  • 代入 = += -= *= /= %= <<= >>= &= |= ^=
  • 括弧 ( ) { } [ ]
  • 区切り文字 . : ; ,
token.hpp
namespace token {
    class Plus : public Token {
        void debug_print() const override;
    };
    class Hyphen : public Token {
        void debug_print() const override;
    };
    /* 以下略 */
}
token.cpp
#define define_debug_print(token) \
    void token::debug_print() const { \
        std::cout << #token << std::endl; \
    }

namespace token {
    define_debug_print(Plus)
    define_debug_print(Hyphen)
    /* 略 */
}

いずれここにたくさん純粋仮想関数を追加する.

使える文字の中ではあと #? が残ってる.