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