aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/parser.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-01-30 15:21:42 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-01-30 15:21:42 +0000
commitc5baaafae69394082817ede9e6eb3910c4601a72 (patch)
treebfc2599717c4274e16ba02959617254873c0c007 /src/libexpr/parser.cc
parentabd1878b26200ba3fa75592637aa87e04f52100d (diff)
* 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.
Diffstat (limited to 'src/libexpr/parser.cc')
-rw-r--r--src/libexpr/parser.cc154
1 files changed, 42 insertions, 112 deletions
diff --git a/src/libexpr/parser.cc b/src/libexpr/parser.cc
index 1e0ef0c45..167c34bd8 100644
--- a/src/libexpr/parser.cc
+++ b/src/libexpr/parser.cc
@@ -5,133 +5,63 @@
#include <fcntl.h>
#include <unistd.h>
-extern "C" {
-#include <sglr.h>
-#include <asfix2.h>
-}
-
#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(<str>)",
- string(s, 1, s.size() - 2).c_str());
-
- if (atMatch(m, e) >> "Path" >> s)
- return ATmake("Path(<str>)", absPath(s, basePath).c_str());
-
- if (atMatch(m, e) >> "Int" >> s) {
- istringstream s2(s);
- int n;
- s2 >> n;
- return ATmake("Int(<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));
}