OSDN Git Service

delimiter.h/cppを、term_lexer、term_checkerとしてテンプレートを利用するように分離した。
[simplecms/utakata.git] / src / lexer / term_checker.cpp
1 #include "src/lexer/term_checker.h"
2 #include "src/unicode.h"
3 #include "src/encoding_reader.h"
4
5 namespace term = utakata::lexer::term;
6 namespace unicode = utakata::unicode;
7 namespace reader = utakata::reader;
8
9 // 宣言のコメントを参照してください。
10 bool term::Delimiter::operator()(reader::EncodingReader* reader,
11                                  unsigned int* size) {
12   unicode::UniChar ch(reader->Peek());
13   switch (ch.rawcode()) {
14     case '(':
15     case '[':
16     case ')':
17     case ']':
18     case '"':
19     case ';':
20     case '#':
21       *size = 1;
22       return true;
23     default:
24       return term::Whitespace()(reader, size);
25   }
26 }
27
28
29 // 宣言のコメントを参照してください。
30 bool term::Whitespace::operator()(reader::EncodingReader* reader,
31                                          unsigned int* size) {
32   unicode::UniChar ch(reader->Peek());
33   switch (ch.rawcode()) {
34     case '\r':                  // carriage return
35     case '\n':                  // linefeed
36     case ' ':                   // space
37     case '\t':                  // tab
38     case '\v':                  // vertical tab
39     case '\f':                  // page
40       *size = 1;
41       return true;
42     default:
43       return false;
44   }
45 }
46
47 // targetが\rである場合、次の一文字のチェックも必要となりますが、
48 // \r単体である場合でも、改行として見做されます。
49 bool term::LineEnding::operator()(reader::EncodingReader* reader,
50                                          unsigned int* size) {
51   unicode::UniChar ch(reader->Peek());
52   switch (ch.rawcode()) {
53     case '\n':
54       *size = 1;
55       return true;
56     case '\r': {
57       unicode::UniString ch2(reader->Peek(2));
58       if (ch2.At(0).rawcode() == '\r' && ch2.At(1).rawcode() == '\n') {
59         *size = 2;
60       } else {
61         *size = 1;
62       }
63       return true;
64     }
65     default:
66       return false;
67   }
68 }
69
70 // 宣言のコメントを参照してください。
71 bool term::HexValue::operator()(reader::EncodingReader* reader,
72                                 unsigned int* size) {
73   unicode::UniChar ch(reader->Peek());
74   if (('a' <= ch.rawcode() && ch.rawcode() <= 'f') ||
75       ('A' <= ch.rawcode() && ch.rawcode() <= 'F') ||
76       ('0' <= ch.rawcode() && ch.rawcode() <= '9')) {
77     *size = 1;
78     return true;
79   }
80   return false;
81 }
82
83 // 宣言のコメントを参照してください。
84 bool term::StringDoubleQuote::operator()(reader::EncodingReader* reader,
85                                          unsigned int* size) {
86   unicode::UniChar ch(reader->Peek());
87   if (ch.rawcode() == '"') {
88     *size = 1;
89     return true;
90   }
91   return false;
92 }
93
94 // prefixは2文字未満である場合は正常なプレフィックスでは無いとして処理を行いません。
95 bool term::NumberPrefixChecker::operator()(const unicode::UniString& str) {
96   if (str.GetSize() < 2) {
97     return false;
98   }
99
100   const unicode::UniChar& first_sharp = str.At(0);
101   const unicode::UniChar& radix_type = str.At(0);
102   if (first_sharp.rawcode() == '#') {
103     if (radix_type.rawcode() == 'b' || radix_type.rawcode() == 'B' ||
104         radix_type.rawcode() == 'o' || radix_type.rawcode() == 'O' ||
105         radix_type.rawcode() == 'x' || radix_type.rawcode() == 'X' ||
106         radix_type.rawcode() == 'd' || radix_type.rawcode() == 'D') {
107       return true;
108     }
109   }
110   return false;
111 }
112
113 // exactnessは2文字であるため、渡された文字列のサイズが2未満である場合には
114 // exactnessとみなしません。
115 bool term::NumberExactnessChecker::operator()(
116     const unicode::UniString& str) {
117   if (str.GetSize() < 2) {
118     return false;
119   }
120
121   unicode::UniChar first_sharp = str.At(0);
122   unicode::UniChar exact_type = str.At(1);
123
124   if (first_sharp.rawcode() == '#') {
125     if (exact_type.rawcode() == 'i' || exact_type.rawcode() == 'I' ||
126         exact_type.rawcode() == 'e' || exact_type.rawcode() == 'E') {
127       return true;
128     }
129   }
130   return false;
131 }