mirror of https://gitlab.com/basile.b/dexed.git
145 lines
4.5 KiB
D
145 lines
4.5 KiB
D
module parser;
|
|
|
|
import
|
|
dparse.lexer, dparse.ast, dparse.parser, dparse.rollback_allocator;
|
|
import
|
|
iz;
|
|
|
|
/**
|
|
* By default libdparse outputs errors and warnings to the standard streams.
|
|
* This function prevents that.
|
|
*/
|
|
void ignoreErrors(string, size_t, size_t, string, bool) @system {}
|
|
|
|
/// dparse Parser with bound checks fixed
|
|
final class Parser : dparse.parser.Parser
|
|
{
|
|
override PragmaExpression parsePragmaExpression()
|
|
{
|
|
mixin (traceEnterAndExit!(__FUNCTION__));
|
|
auto startIndex = index;
|
|
auto node = allocator.make!PragmaExpression;
|
|
mixin(tokenCheck!"pragma");
|
|
mixin(tokenCheck!"(");
|
|
const ident = expect(tok!"identifier");
|
|
mixin(nullCheck!`ident`);
|
|
node.identifier = *ident;
|
|
if (currentIs(tok!","))
|
|
{
|
|
advance();
|
|
mixin(parseNodeQ!(`node.argumentList`, `ArgumentList`));
|
|
}
|
|
mixin(tokenCheck!")");
|
|
node.tokens = tokens[startIndex .. index];
|
|
return node;
|
|
}
|
|
|
|
override TemplateValueParameterDefault parseTemplateValueParameterDefault()
|
|
{
|
|
mixin(traceEnterAndExit!(__FUNCTION__));
|
|
auto startIndex = index;
|
|
auto node = allocator.make!TemplateValueParameterDefault;
|
|
mixin(tokenCheck!"=");
|
|
if (!moreTokens)
|
|
{
|
|
error("template argument default value expected instead of EOF");
|
|
return null;
|
|
}
|
|
switch (current.type)
|
|
{
|
|
case tok!"__FILE__":
|
|
case tok!"__FILE_FULL_PATH__":
|
|
case tok!"__MODULE__":
|
|
case tok!"__LINE__":
|
|
case tok!"__FUNCTION__":
|
|
case tok!"__PRETTY_FUNCTION__":
|
|
node.token = advance();
|
|
break;
|
|
default:
|
|
mixin(parseNodeQ!(`node.assignExpression`, `AssignExpression`));
|
|
break;
|
|
}
|
|
node.tokens = tokens[startIndex .. index];
|
|
return node;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Params:
|
|
* parserConfig = a parser configuration.
|
|
* Returns:
|
|
* The parsed module.
|
|
*/
|
|
Module parseModule(P = .Parser)(auto ref ParserConfig parserConfig)
|
|
{
|
|
auto parser = new P();
|
|
with (parserConfig)
|
|
{
|
|
parser.fileName = fileName;
|
|
parser.tokens = tokens;
|
|
parser.messageFunction = messageFunction;
|
|
parser.messageDelegate = messageDelegate;
|
|
parser.allocator = allocator;
|
|
}
|
|
Module mod = parser.parseModule();
|
|
with (parserConfig)
|
|
{
|
|
if (warningCount !is null)
|
|
*warningCount = parser.warningCount;
|
|
if (errorCount !is null)
|
|
*errorCount = parser.errorCount;
|
|
}
|
|
return mod;
|
|
}
|
|
|
|
/**
|
|
* Params:
|
|
* tokens = The tokens parsed by dparse.lexer.
|
|
* fileName = The name of the file being parsed.
|
|
* allocator = A pointer to a rollback allocator.
|
|
* messageFuncOrDg = Either a function or a delegate that receives the parser messages.
|
|
* errorCount = An optional pointer to a variable receiving the error count.
|
|
* warningCount = An optional pointer to a variable receiving the warning count.
|
|
* Returns:
|
|
* The parsed module.
|
|
*/
|
|
Module parseModule(P = .Parser,F)(const(Token)[] tokens, string fileName, RollbackAllocator* allocator,
|
|
F messageFuncOrDg = null, uint* errorCount = null, uint* warningCount = null)
|
|
{
|
|
static if (is(F))
|
|
{
|
|
static if (is(F : MessageFunction))
|
|
return ParserConfig(tokens, fileName, allocator, messageFuncOrDg, null,
|
|
errorCount, warningCount).parseModule();
|
|
else static if (is(F : MessageDelegate))
|
|
return ParserConfig(tokens, fileName, allocator, null, messageFuncOrDg,
|
|
errorCount, warningCount).parseModule();
|
|
else static assert(0, "F must be a MessageFunction or a MessageDelegate");
|
|
}
|
|
else
|
|
{
|
|
return ParserConfig(tokens, fileName, allocator, null, null, null, null).parseModule!P();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Produces and visits the AST for a source code.
|
|
*
|
|
* This function is used to handle the content of a MixinExpression in an
|
|
* ASTVisitor.
|
|
*/
|
|
T parseAndVisit(T : ASTVisitor, A...)(const(char)[] source, A a)
|
|
{
|
|
import std.functional;
|
|
|
|
RollbackAllocator allocator;
|
|
LexerConfig config = LexerConfig("", StringBehavior.source, WhitespaceBehavior.skip);
|
|
StringCache cache = StringCache(StringCache.defaultBucketCount);
|
|
const(Token)[] tokens = getTokensForParser(cast(ubyte[]) source, config, &cache);
|
|
Module mod = parseModule(tokens, "", &allocator, toDelegate(&ignoreErrors));
|
|
T result = construct!(T)(a);
|
|
result.visit(mod);
|
|
return result;
|
|
}
|
|
|