about summary refs log tree commit diff
path: root/src/libexpr/parser.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-01-30T15·21+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-01-30T15·21+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 1e0ef0c45b..167c34bd83 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));
 }