summaryrefslogtreecommitdiff
path: root/graphics/asymptote/parser.cc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/asymptote/parser.cc
Initial commit
Diffstat (limited to 'graphics/asymptote/parser.cc')
-rw-r--r--graphics/asymptote/parser.cc180
1 files changed, 180 insertions, 0 deletions
diff --git a/graphics/asymptote/parser.cc b/graphics/asymptote/parser.cc
new file mode 100644
index 0000000000..c12a47c50e
--- /dev/null
+++ b/graphics/asymptote/parser.cc
@@ -0,0 +1,180 @@
+/*****
+ * parser.cc
+ * Tom Prince 2004/01/10
+ *
+ *****/
+
+#include <fstream>
+#include <sstream>
+#include <cstring>
+#include <fcntl.h>
+
+#include "common.h"
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include "interact.h"
+#include "locate.h"
+#include "errormsg.h"
+#include "parser.h"
+#include "util.h"
+
+// The lexical analysis and parsing functions used by parseFile.
+void setlexer(size_t (*input) (char* bif, size_t max_size), string filename);
+extern bool yyparse(void);
+extern int yydebug;
+extern int yy_flex_debug;
+extern bool lexerEOF();
+extern void reportEOF();
+extern bool hangup;
+
+static int fd;
+
+namespace parser {
+
+static FILE *fin=NULL;
+
+namespace yy { // Lexers
+
+std::streambuf *sbuf = NULL;
+
+size_t stream_input(char *buf, size_t max_size)
+{
+ return sbuf ? sbuf->sgetn(buf,max_size) : 0;
+}
+
+int fpeek(int fd)
+{
+ int flags=fcntl(fd,F_GETFL,0);
+ fcntl(fd,F_SETFL,flags | O_NONBLOCK);
+ char c=fgetc(fin);
+ ungetc(c,fin);
+ fcntl(fd,F_SETFL,flags & ~O_NONBLOCK);
+ return c;
+}
+
+size_t pipe_input(char *buf, size_t max_size)
+{
+ if(hangup && fpeek(fd) == EOF) {hangup=false; return 0;}
+ fgets(buf,max_size-1,fin);
+ return strlen(buf);
+}
+
+} // namespace yy
+
+void debug(bool state)
+{
+ // For debugging the machine-generated lexer and parser.
+ yy_flex_debug = yydebug = state;
+}
+
+namespace {
+void error(const string& filename)
+{
+ em.sync();
+ em << "error: could not load module '" << filename << "'\n";
+ em.sync();
+ throw handled_error();
+}
+}
+
+absyntax::file *doParse(size_t (*input) (char* bif, size_t max_size),
+ const string& filename, bool extendable=false)
+{
+ setlexer(input,filename);
+ absyntax::file *root = yyparse() == 0 ? absyntax::root : 0;
+ absyntax::root = 0;
+ yy::sbuf = 0;
+
+ if (!root) {
+ if (lexerEOF()) {
+ if (extendable) {
+ return 0;
+ } else {
+ // Have the lexer report the error.
+ reportEOF();
+ }
+ }
+
+ em.error(nullPos);
+ if(!interact::interactive)
+ error(filename);
+ else
+ throw handled_error();
+ }
+
+ return root;
+}
+
+absyntax::file *parseStdin()
+{
+ debug(false);
+
+ if(!fin) {
+ fd=intcast(settings::getSetting<Int>("inpipe"));
+ if(fd >= 0)
+ fin=fdopen(fd,"r");
+ }
+
+ if(fin)
+ return doParse(yy::pipe_input,"-");
+ else {
+ yy::sbuf = cin.rdbuf();
+ return doParse(yy::stream_input,"-");
+ }
+}
+
+absyntax::file *parseFile(const string& filename,
+ const char *nameOfAction)
+{
+ if(filename == "-")
+ return parseStdin();
+
+ string file = settings::locateFile(filename);
+
+ if(file.empty())
+ error(filename);
+
+ if(nameOfAction && settings::verbose > 1)
+ cerr << nameOfAction << " " << filename << " from " << file << endl;
+
+ debug(false);
+
+ std::filebuf filebuf;
+ if(!filebuf.open(file.c_str(),std::ios::in))
+ error(filename);
+
+#ifdef HAVE_SYS_STAT_H
+ // Check that the file is not a directory.
+ static struct stat buf;
+ if(stat(file.c_str(),&buf) == 0) {
+ if(S_ISDIR(buf.st_mode))
+ error(filename);
+ }
+#endif
+
+ // Check that the file can actually be read.
+ try {
+ filebuf.sgetc();
+ } catch (...) {
+ error(filename);
+ }
+
+ yy::sbuf = &filebuf;
+ return doParse(yy::stream_input,file);
+}
+
+absyntax::file *parseString(const string& code,
+ const string& filename,
+ bool extendable)
+{
+ debug(false);
+ stringbuf buf(code);
+ yy::sbuf = &buf;
+ return doParse(yy::stream_input,filename,extendable);
+}
+
+} // namespace parser
+