From c5baaafae69394082817ede9e6eb3910c4601a72 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 30 Jan 2004 15:21:42 +0000 Subject: * Replaced the SDF parser by a substantially faster Bison/Flex parser (roughly 80x faster). The absolutely latest version of Bison (1.875c) is required for reentrant GLR support, as well as a recent version of Flex (say, 2.5.31). Note that most Unix distributions ship with the prehistoric Flex 2.5.4, which doesn't support reentrancy. --- src/libexpr/parser.cc | 154 ++++++++++++++------------------------------------ 1 file changed, 42 insertions(+), 112 deletions(-) (limited to 'src/libexpr/parser.cc') diff --git a/src/libexpr/parser.cc b/src/libexpr/parser.cc index 1e0ef0c45be8..167c34bd83e4 100644 --- a/src/libexpr/parser.cc +++ b/src/libexpr/parser.cc @@ -5,133 +5,63 @@ #include #include -extern "C" { -#include -#include -} - #include "aterm.hh" #include "parser.hh" -#include "parse-table.h" -/* Cleanup cleans up an imploded parse tree into an actual abstract - syntax tree that we can evaluate. It removes quotes around - strings, converts integer literals into actual integers, and - absolutises paths relative to the directory containing the input - file. */ -struct Cleanup : TermFun +struct ParseData { + Expr result; string basePath; + string location; + string error; +}; - virtual ATerm operator () (ATerm e) - { - checkInterrupt(); - - ATMatcher m; - string s; - - if (atMatch(m, e) >> "Str" >> s) - return ATmake("Str()", - string(s, 1, s.size() - 2).c_str()); - - if (atMatch(m, e) >> "Path" >> s) - return ATmake("Path()", absPath(s, basePath).c_str()); - - if (atMatch(m, e) >> "Int" >> s) { - istringstream s2(s); - int n; - s2 >> n; - return ATmake("Int()", n); - } - - if (atMatch(m, e) >> "Var" >> "true") - return ATmake("Bool(True)"); - - if (atMatch(m, e) >> "Var" >> "false") - return ATmake("Bool(False)"); - - if (atMatch(m, e) >> "ExprNil") - return (ATerm) ATempty; +extern "C" { - ATerm e1; - ATermList e2; - if (atMatch(m, e) >> "ExprCons" >> e1 >> e2) - return (ATerm) ATinsert(e2, e1); +#include "parser-tab.h" +#include "lexer-tab.h" + + /* Callbacks for getting from C to C++. Due to a (small) bug in the + GLR code of Bison we cannot currently compile the parser as C++ + code. */ + + void setParseResult(ParseData * data, ATerm t) + { + data->result = t; + } - return e; + ATerm absParsedPath(ParseData * data, ATerm t) + { + return string2ATerm(absPath(aterm2String(t), data->basePath).c_str()); } -}; + + void parseError(ParseData * data, char * error, int line, int column) + { + data->error = (format("%1%, at line %2%, column %3%, of %4%") + % error % line % column % data->location).str(); + } + + int yyparse(yyscan_t scanner, ParseData * data); +} static Expr parse(const char * text, const string & location, const Path & basePath) { - /* Initialise the SDF libraries. */ - static bool initialised = false; - static ATerm parseTable = 0; - static language lang = 0; - - if (!initialised) { - PT_initMEPTApi(); - PT_initAsFix2Api(); - SGinitParser(ATfalse); - - ATprotect(&parseTable); - parseTable = ATreadFromBinaryString( - (char *) nixParseTable, sizeof nixParseTable); - if (!parseTable) - throw Error(format("cannot construct parse table term")); - - ATprotect(&lang); - lang = ATmake("Nix"); - if (!SGopenLanguageFromTerm("nix-parse", lang, parseTable)) - throw Error(format("cannot open language")); - - SG_STARTSYMBOL_ON(); - SG_OUTPUT_ON(); - SG_ASFIX2ME_ON(); - SG_AMBIGUITY_ERROR_ON(); - SG_FILTER_OFF(); - - initialised = true; - } - - /* Parse it. */ - ATerm result = SGparseString(lang, "Expr", (char *) text); - if (!result) - throw SysError(format("parse failed in `%1%'") % location); - if (SGisParseError(result)) - throw Error(format("parse error in `%1%': %2%") - % location % result); - - /* Implode it. */ - PT_ParseTree tree = PT_makeParseTreeFromTerm(result); - if (!tree) - throw Error(format("cannot create parse tree")); + yyscan_t scanner; + ParseData data; + data.basePath = basePath; + data.location = location; + + yylex_init(&scanner); + yy_scan_string(text, scanner); + int res = yyparse(scanner, &data); + yylex_destroy(scanner); - ATerm imploded = PT_implodeParseTree(tree, - ATtrue, - ATtrue, - ATtrue, - ATtrue, - ATtrue, - ATtrue, - ATfalse, - ATtrue, - ATtrue, - ATtrue, - ATfalse); - if (!imploded) - throw Error(format("cannot implode parse tree")); - - printMsg(lvlVomit, format("imploded parse tree of `%1%': %2%") - % location % imploded); - - /* Finally, clean it up. */ - Cleanup cleanup; - cleanup.basePath = basePath; - return bottomupRewrite(cleanup, imploded); + if (res) throw Error(data.error); + + return data.result; } @@ -171,7 +101,7 @@ Expr parseExprFromFile(Path path) readFull(fd, (unsigned char *) text, st.st_size); text[st.st_size] = 0; - return parse(text, path, dirOf(path)); + return parse(text, "`" + path + "'", dirOf(path)); } -- cgit 1.4.1