--- /dev/null
+
+#include "TToken.hh"
+#include "TPushLexer.hh"
+#include "APushParser.hh"
+
+TPushLexer::TPushLexer(APushParser& p) : APushLexer(p)
+{
+ state = ACCEPT;
+}
+
+void
+TPushLexer::reset()
+{
+ buffer.erase();
+ state = ACCEPT;
+}
+
+void
+TPushLexer::transaction(char ch, State newState)
+{
+ switch (ch)
+ {
+ case '{': parser.push(TToken(TToken::BEGIN)); break;
+ case '}': parser.push(TToken(TToken::END)); break;
+ case '$': parser.push(TToken(TToken::SHIFT)); break;
+ case '&': parser.push(TToken(TToken::ALIGN)); break;
+ case '\n':
+ case '\r': parser.push(TToken(TToken::EOL, ch)); break;
+ case '^': parser.push(TToken(TToken::SUPERSCRIPT)); break;
+ case '_': parser.push(TToken(TToken::SUBSCRIPT)); break;
+ case '\t':
+ case ' ': parser.push(TToken(TToken::SPACE, ch)); break;
+ case '~': parser.push(TToken(TToken::ACTIVE, ch)); break;
+ case '%': parser.push(TToken(TToken::COMMENT)); break;
+ default:
+ if (isalpha(ch)) parser.push(TToken(TToken::LETTER, ch));
+ else if (isdigit(ch)) parser.push(TToken(TToken::DIGIT, ch));
+ else parser.push(TToken(TToken::OTHER, ch));
+ break;
+ }
+ state = newState;
+}
+
+void
+TPushLexer::push(char ch)
+{
+ switch (state)
+ {
+ case ACCEPT:
+ if (ch == '\\') state = ESCAPE;
+ else if (ch == '#') state = PARAMETER;
+ else transaction(ch, ACCEPT);
+ break;
+ case ESCAPE:
+ if (isalpha(ch))
+ {
+ buffer.push_back(ch);
+ state = MACRO;
+ }
+ else
+ {
+ parser.push(TToken(TToken::CONTROL, ch));
+ state = ACCEPT;
+ }
+ break;
+ case MACRO:
+ if (ch == '\\')
+ {
+ parser.push(TToken(TToken::CONTROL, buffer));
+ buffer.erase();
+ state = ESCAPE;
+ }
+ else if (ch == '#')
+ {
+ parser.push(TToken(TToken::CONTROL, buffer));
+ buffer.erase();
+ state = PARAMETER;
+ }
+ else if (isalpha(ch))
+ buffer.push_back(ch);
+ else
+ {
+ parser.push(TToken(TToken::CONTROL, buffer));
+ buffer.erase();
+ if (isspace(ch)) state = IGNORE_SPACE;
+ else transaction(ch, ACCEPT);
+ }
+ break;
+ case IGNORE_SPACE:
+ if (ch == '\\') state = ESCAPE;
+ else if (ch == '#') state = PARAMETER;
+ else if (isspace(ch)) ;
+ else transaction(ch, ACCEPT);
+ break;
+ case PARAMETER:
+ parser.push(TToken(TToken::PARAMETER, ch));
+ state = ACCEPT;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ switch (state)
+ {
+ case ESCAPE: parser.setCursor("\\"); break;
+ case MACRO: parser.setCursor("\\" + buffer); break;
+ case PARAMETER: parser.setCursor("#"); break;
+ default: parser.setCursor("?"); break;
+ }
+}
+
+bool
+TPushLexer::error() const
+{
+ return false;
+}