Skip to content

Commit

Permalink
Add support for parsing LSL from an in-memory buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
SaladDais committed Oct 19, 2022
1 parent 23fa575 commit fe7dcaa
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 20 deletions.
2 changes: 1 addition & 1 deletion fuzz/fuzz.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

Tailslide::ScopedScriptParser parser(nullptr);
try {
auto *script = parser.parseLSL(file);
auto *script = parser.parseLSLFile(file);
if (script) {
script->collectSymbols();
script->determineTypes();
Expand Down
1 change: 1 addition & 0 deletions libtailslide/lslmini.hh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct ScriptContext {
// any nodes created while this is false will be considered synthetic by default
bool parsing = false;
Tailslide::TailslideLType glloc {0};
void *scanner = nullptr;
};

struct Vector3 {
Expand Down
2 changes: 1 addition & 1 deletion libtailslide/passes/desugaring.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Tailslide {

// any time an int appears in a binary expression with these it must be promoted
std::vector<LSLIType> SIBLINGS_CAUSING_INT_PROMOTION = {
static const std::vector<LSLIType> SIBLINGS_CAUSING_INT_PROMOTION = {
LST_FLOATINGPOINT,
LST_VECTOR,
LST_QUATERNION,
Expand Down
39 changes: 25 additions & 14 deletions libtailslide/tailslide.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include "lslmini.tab.hh"

int tailslide_lex_init_extra(Tailslide::ScriptContext *, void **);

void tailslide_set_in(FILE *, void *);
void *tailslide__scan_bytes ( const char *bytes, int len, void *);

int tailslide_lex_destroy(void *);

Expand All @@ -31,43 +31,54 @@ class FileCloser {
FILE *_mFile;
};

LSLScript *ScopedScriptParser::parseLSL(const std::string &filename) {
LSLScript *ScopedScriptParser::parseLSLFile(const std::string &filename) {
// can only be used to parse a single script.
assert(!script);
FILE *yyin = fopen(filename.c_str(), "rb");
if (yyin == nullptr) {
throw "couldn't open file";
}
FileCloser closer(yyin);
auto result = parseLSL(yyin);
return result;
return parseLSLFile(yyin);
}

LSLScript *ScopedScriptParser::parseLSLFile(FILE *yyin) {
initScanner();
// set input file
tailslide_set_in(yyin, context.scanner);
parseInternal();
return script;
}

LSLScript *ScopedScriptParser::parseLSLBytes(const char *buf, int buf_len) {
initScanner();
// set input file
tailslide__scan_bytes(buf, buf_len, context.scanner);
parseInternal();
return script;
}

LSLScript *ScopedScriptParser::parseLSL(FILE *yyin) {
void ScopedScriptParser::initScanner() {
assert(!script);
void *scanner;
// ScopedScriptParser owns the allocator and context instance because we can't
// reasonably re-use Allocator instances with our current model of having
// it magically pass along the current script context.
allocator.setContext(&context);

// initialize flex
tailslide_lex_init_extra(&context, &scanner);

// set input file
tailslide_set_in(yyin, scanner);
tailslide_lex_init_extra(&context, &context.scanner);
}

void ScopedScriptParser::parseInternal() {
// parse
context.parsing = true;
tailslide_parse(scanner);
tailslide_parse(context.scanner);
context.parsing = false;

// clean up flex
tailslide_lex_destroy(scanner);
tailslide_lex_destroy(context.scanner);
ast_sane = context.ast_sane;
script = context.script;

return script;
}

}
9 changes: 7 additions & 2 deletions libtailslide/tailslide.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ struct ScopedScriptParser {
ScriptContext context;
LSLSymbolTableManager table_manager;

LSLScript *parseLSL(FILE *yyin);
LSLScript *parseLSL(const std::string &filename);
LSLScript *parseLSLFile(FILE *yyin);
LSLScript *parseLSLFile(const std::string &filename);
LSLScript *parseLSLBytes(const char *buf, int buf_len);

protected:
void initScanner();
void parseInternal();
};

}
Expand Down
2 changes: 1 addition & 1 deletion tailslide_cli/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ int main(int argc, char **argv) {
if (check_assertions)
logger->setCheckAssertions(true);

auto script = parser.parseLSL(yyin);
auto script = parser.parseLSLFile(yyin);
if (yyin != nullptr)
fclose(yyin);

Expand Down
9 changes: 9 additions & 0 deletions tests/conformance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,13 @@ TEST_CASE("jump_kinds.lsl") {
checkTreeDumpOutput("jump_kinds.lsl", OptimizationOptions{});
}

static const char *SIMPLE_SCRIPT_BYTES = "default{state_entry(){}}";

TEST_CASE("Parse script buffer") {
ParserRef parser(new ScopedScriptParser(nullptr));
auto script = parser->parseLSLBytes(SIMPLE_SCRIPT_BYTES, (int)strlen(SIMPLE_SCRIPT_BYTES));
CHECK_NE(nullptr, script);
CHECK_EQ(0, parser->logger.getErrors());
}

TEST_SUITE_END();
2 changes: 1 addition & 1 deletion tests/testutils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ ParserRef runConformance(const char *name, bool allow_syntax_errors)
ParserRef parser(new ScopedScriptParser(nullptr));
Logger *logger = &parser->logger;
logger->setCheckAssertions(true);
parser->parseLSL(path);
parser->parseLSLFile(path);
LSLScript *script = parser->script;

if (script == nullptr)
Expand Down

0 comments on commit fe7dcaa

Please sign in to comment.