|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
-*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
(c) COPYRIGHT URI/MIT 1994-1999
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
Scanner for constraint expressions. The scanner returns tokens for each of
|
|
Packit |
a4aae4 |
the relational and selection operators. It requires GNU flex version 2.5.2
|
|
Packit |
a4aae4 |
or newer.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
The scanner is not reentrant, but can share a name space with other
|
|
Packit |
a4aae4 |
scanners.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Note:
|
|
Packit |
a4aae4 |
1) The `defines' file expr.tab.h is built using `bison -d'.
|
|
Packit |
a4aae4 |
2) Define YY_DECL such that the scanner is called `exprlex'.
|
|
Packit |
a4aae4 |
3) When bison builds the expr.tab.h file, it uses `expr' instead of `yy'
|
|
Packit |
a4aae4 |
for variable name prefixes (e.g., yylval --> exprlval).
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
jhrg 9/5/95
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%{
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cstdio>
|
|
Packit |
a4aae4 |
#include <string>
|
|
Packit |
a4aae4 |
#include <cstring>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifndef YY_PROTO
|
|
Packit |
a4aae4 |
#define YY_PROTO(proto) proto
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#define YY_DECL int ce_exprlex YY_PROTO(( void ))
|
|
Packit |
a4aae4 |
#define YY_FATAL_ERROR(msg) {\
|
|
Packit |
a4aae4 |
throw(libdap::Error(malformed_expr, std::string("Error scanning constraint expression text: ") + std::string(msg))); \
|
|
Packit |
a4aae4 |
yy_fatal_error(msg); /* see das.lex */ \
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Error.h"
|
|
Packit |
a4aae4 |
#include "parser.h"
|
|
Packit |
a4aae4 |
#include "expr.h"
|
|
Packit |
a4aae4 |
#include "RValue.h"
|
|
Packit |
a4aae4 |
#include "ce_expr.tab.hh"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace libdap ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static void store_id();
|
|
Packit |
a4aae4 |
static void store_str();
|
|
Packit |
a4aae4 |
static void store_op(int op);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%option noyywrap
|
|
Packit |
a4aae4 |
%option nounput
|
|
Packit |
a4aae4 |
%option noinput
|
|
Packit |
a4aae4 |
%option 8bit
|
|
Packit |
a4aae4 |
%option prefix="ce_expr"
|
|
Packit |
a4aae4 |
%option outfile="lex.ce_expr.cc"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%x quote
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* In the DAS and DDS parsers I removed the INT and FLOAT lexemes. However,
|
|
Packit |
a4aae4 |
not having them here complicates parsing since you must check to see if a
|
|
Packit |
a4aae4 |
word is a number (like 2.3) or a variable called `2.3.' I'm assuming that
|
|
Packit |
a4aae4 |
people will always put some characters in variable names (e.g., they'll
|
|
Packit |
a4aae4 |
use `2300.7%20MHz' and not just `2300.7'). If that turns out to be a bad
|
|
Packit |
a4aae4 |
assumption, the we'll have to put more code in the parser to figure out
|
|
Packit |
a4aae4 |
what exactly each word is; is it a constant or a variable name. Time will
|
|
Packit |
a4aae4 |
tell. 10/31/2001 jhrg */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
NAN [Nn][Aa][Nn]
|
|
Packit |
a4aae4 |
INF [Ii][Nn][Ff]
|
|
Packit |
a4aae4 |
/* See das.lex for comments about the characters allowed in a WORD.
|
|
Packit |
a4aae4 |
10/31/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
I've added '*' to the set of characters in a WORD for both the DDS and DAS
|
|
Packit |
a4aae4 |
scanners, but not here because it'll conflict with the url dereference
|
|
Packit |
a4aae4 |
operator. 6/10/2002 jhrg
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
SCAN_WORD [-+a-zA-Z0-9_/%.\\][-+a-zA-Z0-9_/%.\\#]*
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
SCAN_EQUAL =
|
|
Packit |
a4aae4 |
SCAN_NOT_EQUAL !=
|
|
Packit |
a4aae4 |
SCAN_GREATER >
|
|
Packit |
a4aae4 |
SCAN_GREATER_EQL >=
|
|
Packit |
a4aae4 |
SCAN_LESS <
|
|
Packit |
a4aae4 |
SCAN_LESS_EQL <=
|
|
Packit |
a4aae4 |
SCAN_REGEXP =~
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
SCAN_HASH_BYTE $Byte
|
|
Packit |
a4aae4 |
SCAN_HASH_INT16 $Int16
|
|
Packit |
a4aae4 |
SCAN_HASH_UINT16 $UInt16
|
|
Packit |
a4aae4 |
SCAN_HASH_INT32 $Int32
|
|
Packit |
a4aae4 |
SCAN_HASH_UINT32 $UInt32
|
|
Packit |
a4aae4 |
SCAN_HASH_FLOAT32 $Float32
|
|
Packit |
a4aae4 |
SCAN_HASH_FLOAT64 $Float64
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
SCAN_STAR \*
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
NEVER [^\-+a-zA-Z0-9_/%.\\:,(){}[\]&<>=~]
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
%%
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
"[" return (int)*yytext;
|
|
Packit |
a4aae4 |
"]" return (int)*yytext;
|
|
Packit |
a4aae4 |
":" return (int)*yytext;
|
|
Packit |
a4aae4 |
"," return (int)*yytext;
|
|
Packit |
a4aae4 |
"&" return (int)*yytext;
|
|
Packit |
a4aae4 |
"(" return (int)*yytext;
|
|
Packit |
a4aae4 |
")" return (int)*yytext;
|
|
Packit |
a4aae4 |
"{" return (int)*yytext;
|
|
Packit |
a4aae4 |
"}" return (int)*yytext;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{SCAN_WORD} store_id(); return SCAN_WORD;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{SCAN_EQUAL} store_op(SCAN_EQUAL); return SCAN_EQUAL;
|
|
Packit |
a4aae4 |
{SCAN_NOT_EQUAL} store_op(SCAN_NOT_EQUAL); return SCAN_NOT_EQUAL;
|
|
Packit |
a4aae4 |
{SCAN_GREATER} store_op(SCAN_GREATER); return SCAN_GREATER;
|
|
Packit |
a4aae4 |
{SCAN_GREATER_EQL} store_op(SCAN_GREATER_EQL); return SCAN_GREATER_EQL;
|
|
Packit |
a4aae4 |
{SCAN_LESS} store_op(SCAN_LESS); return SCAN_LESS;
|
|
Packit |
a4aae4 |
{SCAN_LESS_EQL} store_op(SCAN_LESS_EQL); return SCAN_LESS_EQL;
|
|
Packit |
a4aae4 |
{SCAN_REGEXP} store_op(SCAN_REGEXP); return SCAN_REGEXP;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{SCAN_STAR} store_op(SCAN_STAR); return SCAN_STAR;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{SCAN_HASH_BYTE} return SCAN_HASH_BYTE;
|
|
Packit |
a4aae4 |
{SCAN_HASH_INT16} return SCAN_HASH_INT16;
|
|
Packit |
a4aae4 |
{SCAN_HASH_UINT16} return SCAN_HASH_UINT16;
|
|
Packit |
a4aae4 |
{SCAN_HASH_INT32} return SCAN_HASH_INT32;
|
|
Packit |
a4aae4 |
{SCAN_HASH_UINT32} return SCAN_HASH_UINT32;
|
|
Packit |
a4aae4 |
{SCAN_HASH_FLOAT32} return SCAN_HASH_FLOAT32;
|
|
Packit |
a4aae4 |
{SCAN_HASH_FLOAT64} return SCAN_HASH_FLOAT64;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
[ \t\r\n]+
|
|
Packit |
a4aae4 |
<INITIAL><<EOF>> yy_init = 1; yyterminate();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
\" BEGIN(quote); yymore();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
<quote>[^"\\]* yymore(); /*"*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
<quote>\\. yymore();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
<quote>\" {
|
|
Packit |
a4aae4 |
BEGIN(INITIAL);
|
|
Packit |
a4aae4 |
store_str();
|
|
Packit |
a4aae4 |
return SCAN_STR;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
<quote><<EOF>> {
|
|
Packit |
a4aae4 |
BEGIN(INITIAL); /* resetting the state is needed for reentrant parsers */
|
|
Packit |
a4aae4 |
char msg[256];
|
|
Packit |
a4aae4 |
sprintf(msg, "Unterminated quote\n");
|
|
Packit |
a4aae4 |
YY_FATAL_ERROR(msg);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{NEVER} {
|
|
Packit |
a4aae4 |
if (yytext) { /* suppress msgs about `' chars */
|
|
Packit |
a4aae4 |
fprintf(stderr, "Character `%c' is not", *yytext);
|
|
Packit |
a4aae4 |
fprintf(stderr, " allowed and has been ignored\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
%%
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Three glue routines for string scanning. These are not declared in the
|
|
Packit |
a4aae4 |
// header expr.tab.h nor is YY_BUFFER_STATE. Including these here allows them
|
|
Packit |
a4aae4 |
// to see the type definitions in lex.expr.c (where YY_BUFFER_STATE is
|
|
Packit |
a4aae4 |
// defined) and allows callers to declare them (since callers outside of this
|
|
Packit |
a4aae4 |
// file cannot declare the YY_BUFFER_STATE variable). Note that I changed the
|
|
Packit |
a4aae4 |
// name of the expr_scan_string function to expr_string because C++ cannot
|
|
Packit |
a4aae4 |
// distinguish by return type. 1/12/99 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void *
|
|
Packit |
a4aae4 |
ce_expr_string(const char *str)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return (void *)ce_expr_scan_string(str);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
ce_expr_switch_to_buffer(void *buf)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ce_expr_switch_to_buffer((YY_BUFFER_STATE)buf);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
ce_expr_delete_buffer(void *buf)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ce_expr_delete_buffer((YY_BUFFER_STATE)buf);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static void
|
|
Packit |
a4aae4 |
store_id()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strncpy(ce_exprlval.id, yytext, ID_MAX-1);
|
|
Packit |
a4aae4 |
ce_exprlval.id[ID_MAX-1] = '\0';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static void
|
|
Packit |
a4aae4 |
store_str()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// transform %20 to a space. 7/11/2001 jhrg
|
|
Packit |
a4aae4 |
string *s = new string(yytext); // move all calls of www2id into the parser. jhrg 7/5/13 www2id(string(yytext)));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (*s->begin() == '\"' && *(s->end()-1) == '\"') {
|
|
Packit |
a4aae4 |
s->erase(s->begin());
|
|
Packit |
a4aae4 |
s->erase(s->end()-1);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ce_exprlval.val.type = dods_str_c;
|
|
Packit |
a4aae4 |
ce_exprlval.val.v.s = s;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static void
|
|
Packit |
a4aae4 |
store_op(int op)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ce_exprlval.op = op;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|