Changeset: df1075bd8b7e for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=df1075bd8b7e
Added Files:
        monetdb5/mal/mal_parser.c
        monetdb5/mal/mal_parser.h
Removed Files:
        monetdb5/mal/mal_parser.mx
Modified Files:
        monetdb5/mal/Makefile.ag
Branch: default
Log Message:

de-Mx mal_parser.mx


diffs (truncated from 4072 to 300 lines):

diff --git a/monetdb5/mal/Makefile.ag b/monetdb5/mal/Makefile.ag
--- a/monetdb5/mal/Makefile.ag
+++ b/monetdb5/mal/Makefile.ag
@@ -44,7 +44,7 @@ lib_mal = {
                mal_listing.c mal_listing.h \
                mal_module.c mal_module.h \
                mal_namespace.c mal_namespace.h \
-               mal_parser.mx \
+               mal_parser.c mal_parser.h \
                mal_profiler.c mal_profiler.h \
                mal_properties.c mal_properties.h \
                mal_readline.c mal_readline.h \
diff --git a/monetdb5/mal/mal_parser.c b/monetdb5/mal/mal_parser.c
new file mode 100644
--- /dev/null
+++ b/monetdb5/mal/mal_parser.c
@@ -0,0 +1,1999 @@
+/*
+ * The contents of this file are subject to the MonetDB Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.monetdb.org/Legal/MonetDBLicense
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is the MonetDB Database System.
+ *
+ * The Initial Developer of the Original Code is CWI.
+ * Portions created by CWI are Copyright (C) 1997-July 2008 CWI.
+ * Copyright August 2008-2011 MonetDB B.V.
+ * All Rights Reserved.
+ */
+
+/* Author(s): M. L. Kersten
+ *The Parser Implementation
+ * The parser (and its target language) are designed for speed of analysis.
+ * For, parsing is a dominant cost-factor in applications interfering with
+ * MonetDB. For the language design it meant that look-ahead and ambiguity
+ * is avoided where-ever possible without compromising readability and
+ * to ease debugging.
+ *
+ * The syntax layout of a MAL program consists of a module name,
+ * a list of include commands, a list of function/ pattern/ command/ factory
+ * definitions and concludes with the statements to be executed as
+ * the main body of the program.  All components are optional.
+ *
+ * The program may be decorated with comments, which starts with a # and
+ * runs till the end of the current line. Comments are retained
+ * in the code block for debugging, but can be removed with an optimizer to 
reduce space
+ * and interpretation overhead.
+ *
+ * @+ The lexical analyzer
+ * The implementation of the lexical analyzer is straightforward:
+ * the input is taken from a client input buffer. It is assumed that
+ * this buffer contains the complete MAL structure to be parsed.
+*/
+
+#include "monetdb_config.h"
+#include "mal_parser.h"
+#include "mal_resolve.h"
+#include "mal_linker.h"
+#include "mal_atom.h"       /* for malAtomDefinition(), malAtomArray(), 
malAtomProperty() */
+#include "mal_interpreter.h"    /* for showErrors() */
+#include "mal_instruction.h"    /* for pushEndInstruction(), 
findVariableLength() */
+#include "mal_namespace.h"
+#include "mal_utils.h"
+#include "mal_builder.h"
+
+#define FATALINPUT MAXERRORS+1
+#define NL(X) ((X)=='\n' || (X)=='\r')
+
+static str idCopy(Client cntxt, int len);
+static str strCopy(Client cntxt, int len);
+
+
+/* Before a line is parsed we check for a request to echo it.
+ * This command should be executed at the beginning of a parse
+ * request and each time we encounter EOL.
+*/
+void echoInput(Client cntxt)
+{
+       if (cntxt->listing == 1) {
+               char *c = CURRENT(cntxt);
+               mnstr_printf(cntxt->fdout,"#");
+               while (*c && !NL(*c)) {
+                       mnstr_printf(cntxt->fdout, "%c", *c++);
+               }
+
+               mnstr_printf(cntxt->fdout, "\n");
+       }
+}
+
+static inline void
+skipSpace(Client cntxt)
+{
+       char *s= &currChar(cntxt);
+       for (;;) {
+               switch (*s++) {
+               case ' ':
+               case '\t':
+               case '\n':
+               case '\r':
+                       nextChar(cntxt);
+                       break;
+               default:
+                       return;
+               }
+       }
+}
+
+static inline void
+advance(Client cntxt, int length)
+{
+       cntxt->yycur += length;
+       skipSpace(cntxt);
+}
+
+/*
+ * The most recurring situation is to recognize identifiers.
+ * This process is split into a few steps to simplify subsequent
+ * construction and comparison.
+ * IdLength searches the end of an identifier without changing
+ * the cursor into the input pool.
+ * IdCopy subsequently prepares a GDK string for inclusion in the
+ * instruction datastructures.
+*/
+
+short opCharacter[256];
+short idCharacter[256];
+short idCharacter2[256];
+
+void 
+initParser(void)
+{
+       int i;
+
+       for (i = 0; i < 256; i++){
+               idCharacter2[i]= isalpha(i) || isdigit(i);
+               idCharacter[i] = isalpha(i);
+       }
+       for (i = 0; i < 256; i++)
+       switch(i){
+       case '-': case '!': case '\\': case '$': case '%':
+       case '^': case '*': case '~': case '+': case '&':
+       case '|': case '<': case '>': case '=': case '/':
+       case ':':
+               opCharacter[i]=1;
+       }
+       idCharacter[TMPMARKER]=1;
+       idCharacter2[TMPMARKER]=1;
+       idCharacter2['@']=1;
+}
+
+#undef isdigit
+#define isdigit(X)  ((X)>='0' && (X)<='9')
+
+int
+idLength(Client cntxt)
+{
+       str s,t;
+       skipSpace(cntxt);
+       s = CURRENT(cntxt);
+       t=s;
+
+       if (!idCharacter[(int) (*s)])
+               return 0;
+       /* avoid a clash with old temporaries */
+       if( s[0]== TMPMARKER)
+               s[0]= REFMARKER;
+       /* prepare escape of temporary names */
+       s++;
+       while (idCharacter2[(int) (*s)] )
+               s++;
+       return (int) (s-t);
+}
+
+/* Simple type identifiers can not be marked with a type variable. */
+static int
+typeidLength(Client cntxt)
+{
+       int l;
+       str s;
+       skipSpace(cntxt);
+       s = CURRENT(cntxt);
+
+       if (!idCharacter[(int) (*s)])
+               return 0;
+       l = 1;
+       s++;
+       idCharacter[TMPMARKER] = 0;
+       while (idCharacter[(int) (*s)] || isdigit(*s)) {
+               s++;
+               l++;
+       }
+       idCharacter[TMPMARKER]=1;
+       return l;
+}
+
+static str idCopy(Client cntxt, int length){
+       str s= GDKmalloc(length+1);
+       if ( s == NULL)
+               return NULL;
+       memcpy(s, CURRENT(cntxt),(size_t) length);
+       s[length]=0;
+       /* avoid a clash with old temporaries */
+       if( s[0]== TMPMARKER)
+               s[0]= REFMARKER;
+       advance(cntxt,length);
+       return s;
+}
+
+int
+MALkeyword(Client cntxt, str kw, int length)
+{
+       skipSpace(cntxt);
+       if (MALlookahead(cntxt, kw, length)) {
+               advance(cntxt, length);
+               return 1;
+       }
+       return 0;
+}
+
+int
+MALlookahead(Client cntxt, str kw, int length)
+{
+       int i;
+
+       skipSpace(cntxt);
+       /* avoid double test or use lowercase only. */
+       if (currChar(cntxt) == *kw &&
+               strncmp(CURRENT(cntxt), kw, length) == 0 &&
+               !idCharacter[(int) (CURRENT(cntxt)[length])] &&
+               !isdigit((int) (CURRENT(cntxt)[length])) ) {
+               return 1;
+       }
+        /* check for captialized versions */
+       for (i = 0; i < length; i++)
+               if (tolower(CURRENT(cntxt)[i]) != kw[i])
+                       return 0;
+       if (!idCharacter[(int) (CURRENT(cntxt)[length])] &&
+               !isdigit((int) (CURRENT(cntxt)[length])) ) {
+               return 1;
+       }
+       return 0;
+}
+/*
+ * Keyphrase testing is limited to a few characters only
+ * (check manually). To speed this up we use a pipelined and inline macros.
+*/
+
+static inline int
+keyphrase1(Client cntxt, str kw)
+{
+       skipSpace(cntxt);
+       if (currChar(cntxt) == *kw) {
+               advance(cntxt,1);
+               return 1;
+       }
+       return 0;
+}
+
+static inline int
+keyphrase2(Client cntxt, str kw)
+{
+       skipSpace(cntxt);
+       if (CURRENT(cntxt)[0] == kw[0] && CURRENT(cntxt)[1] == kw[1]) {
+               advance(cntxt,2);
+               return 1;
+       }
+       return 0;
+}
+static inline int
+keyphrase(Client cntxt, str kw,int length)
+{
+       skipSpace(cntxt);
+       if( strncmp(CURRENT(cntxt),kw,length)== 0){
+               advance(cntxt,length);
+               return 1;
+       }
+       return 0;
+}
+/*
+ * A similar approach is used for string literals.
+ * Beware, string lengths returned include the
+ * brackets and escapes. They are eaten away in strCopy.
+ * We should provide the C-method to split strings and
+ * concatenate them upon retrieval[todo]
+*/
+int
+stringLength(Client cntxt)
+{
+       int l=0;
+       int quote =0;
+       str s;
+       skipSpace(cntxt);
+       s = CURRENT(cntxt);
+
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to