blob: 2d6b992fd8d7c40123a6917f7bd1ceac75945a4c [file] [log] [blame]
#include "Parser.h"
#include <QDebug>
Parser::Parser(QString input)
{
_input = input;
}
QChar Parser::peek()
{
if (atEnd())
return 0;
return _input[_pos];
}
QChar Parser::get()
{
return _input[_pos++];
}
bool Parser::atEnd()
{
return _pos >= _input.length();
}
void Parser::skip()
{
while (peek().isSpace())
get();
}
bool Parser::parseSymbol(AstNode *node)
{
skip();
if (peek().isLetter())
{
*node = AstNode(get());
return true;
}
return false;
}
bool Parser::parseIdentifier(AstNode *node)
{
skip();
QString buffer;
if (peek().isUpper())
{
while (peek().isLetter() || peek() == '-' || peek() == '_' || peek().isNumber())
{
buffer += get();
}
*node = AstNode(buffer);
return true;
}
return false;
}
bool Parser::parseNumber(AstNode *node)
{
skip();
QString buffer;
if (peek().isDigit())
{
while (peek().isDigit())
buffer += get();
*node = AstNode(buffer.toInt());
return true;
}
return false;
}
bool Parser::parseVariable(AstNode *node)
{
skip();
int pos = _pos;
if (peek() == 's' || peek() == 'e' || peek() == 't')
{
char type = get().toLatin1();
if (peek() == '.')
{
get();
AstNode identNode;
if (parseIdentifier(&identNode))
{
*node = AstNode(type, identNode.name());
return true;
}
}
}
_pos = pos;
return false;
}
bool Parser::parseOne(AstNode *node)
{
return parseFunction(node) ||
parseVariable(node) ||
parseNumber(node) ||
parseIdentifier(node) ||
parseSymbol(node) ||
parseParens(node);
}
QList<AstNode> Parser::parseMany()
{
QList<AstNode> nodes;
AstNode next;
while (parseOne(&next))
{
nodes.append(next);
}
return nodes;
}
bool Parser::parseParens(AstNode *node)
{
skip();
int pos = _pos;
if (peek() != '(')
return false;
get();
QList<AstNode> many = parseMany();
*node = AstNode(many);
skip();
if (peek() != ')')
{
_pos = pos;
return false;
}
get();
return true;
}
bool Parser::parseFunction(AstNode *node)
{
skip();
int pos = _pos;
if (peek() != '<')
return false;
get();
AstNode head;
if (!parseIdentifier(&head))
{
_pos = pos;
return false;
}
QList<AstNode> body = parseMany();
*node = AstNode(head.name(), body);
skip();
if (peek() != '>')
{
_pos = pos;
return false;
}
get();
return true;
}