📄 mdxparse.cup
字号:
// JavaCup specification for expression evaluator
package com.tonbeller.jpivot.olap.mdxparse;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import java_cup.runtime.Symbol;
action code {: ParsedQuery pQuery = new ParsedQuery(); :};
parser code {:
static Logger logger = Logger.getLogger(parser.class);
/**
* report_error
*/
public void report_error(String message, Object info) {
logger.warn("Parsing MDX:" +message);
if (info instanceof Symbol) {
if (((Symbol)info).left != -1) {
logger.warn("at character " + ((Symbol)info).left + " of input");
}
}
}
/**
* report_fatal_error
*/
public void report_fatal_error(String message, Object info) throws Exception {
String err;
err = "Fatal error parsing MDX:" +message;
if (info instanceof Symbol) {
if (((Symbol)info).left != -1) {
err += "\n at character " + ((Symbol)info).left + " of input";
} else {
err += "\n invalid symbol \"" + ((Symbol)info).value +"\"";
}
} else
err += "\n" + info.toString();
logger.error("Fatal error parsing MDX:" +err);
throw new Exception(err);
}
:};
/* Terminals (tokens returned by the scanner). */
// a. Keywords.
terminal
AND,
AS,
CASE,
CELL,
CELL_ORDINAL,
DIMENSION,
DRILLTHROUGH,
ELSE,
EMPTY,
END,
FROM,
MEMBER,
NON,
NOT,
ON,
OR,
PROPERTIES,
QUOTE,
SELECT,
SET,
THEN,
WHEN,
WHERE,
XOR,
WITH;
// b. Symbols
terminal
ASTERISK, // *
COLON, // :
COMMA, // ,
CONCAT, // ||
DOT, // .
EQ, // =
GE, // >=
GT, // >
LBRACE, // {
LE, // <=
LPAREN, // (
LT, // <
MINUS, // -
NE, // <>
PLUS, // +
RBRACE, // }
RPAREN, // )
SOLIDUS; // /
// c. Typed terminals
terminal Double NUMBER;
terminal String ID;
terminal String QUOTED_ID;
terminal String AMP_QUOTED_ID;
terminal String STRING;
terminal String UNKNOWN; // a token the lexer doesn't like!
/* Non terminals */
non terminal ParsedQuery mdx_statement;
non terminal cube_def;
non terminal slicer_def;
non terminal cell_prop_def, cell_prop_list;
non terminal with_clause;
non terminal select_clause;
non terminal ArrayList formula_spec;
non terminal Formula single_formula_spec, member_spec, set_spec;
non terminal ArrayList axis_def, axis_spec_list;
non terminal QueryAxis axis_spec;
non terminal Exp expression, value_expression, value_expression_opt, case_expression;
non terminal Exp value_expression_primary, term5, term4, term3, term2, term, factor;
non terminal Exp else_clause_opt;
non terminal Exp[] when_clause;
non terminal Boolean non_empty_opt;
non terminal String identifier, axis_name;
non terminal ArrayList comma_member_property_def_list_opt, member_property_def_list;
non terminal ArrayList exp_list_opt, exp_list, when_list;
non terminal MemberProperty member_property_definition;
non terminal CompoundId compound_id;
non terminal String comp_op;
non terminal List dim_props, dim_prop_list;
/* The grammar */
start with mdx_statement;
mdx_statement ::= with_clause sel_clause axis_def FROM cube_def slicer_def cell_prop_def
{: RESULT = pQuery; :};
sel_clause ::= SELECT | DRILLTHROUGH SELECT;
with_clause ::= {: pQuery.formulas = new ArrayList(); /* empty */ :}
| WITH formula_spec:f {: pQuery.formulas = f; :} ;
axis_def ::= /* empty */ {: pQuery.axisDef = new ArrayList(); :}
| axis_spec_list:l {: pQuery.axisDef = l; :};
axis_spec_list ::= axis_spec:i {: RESULT = new ArrayList(); RESULT.add(i); :}
| axis_spec:e COMMA axis_spec_list : list {: list.add(0, e); RESULT = list; :};
axis_spec ::= non_empty_opt:b expression:s dim_props:dprops ON axis_name:a
{: RESULT = new QueryAxis(b.booleanValue(), s, a);
RESULT.setDimProps(dprops); :};
dim_props ::= /* empty */ {: RESULT = new ArrayList(); :}
| DIMENSION PROPERTIES dim_prop_list:dplist {: RESULT = dplist; :};
dim_prop_list ::= compound_id:cid {: List lst = new ArrayList();
lst.add(cid); RESULT = lst; :}
| compound_id:cid2 COMMA dim_prop_list:dpl
{: RESULT = dpl; dpl.add(cid2); :};
non_empty_opt ::= {:RESULT = new Boolean(false); :} /* empty */
| NON EMPTY {: RESULT = new Boolean(true); :};
axis_name ::= identifier:x {: RESULT = x; :};
cube_def ::= identifier:x {: pQuery.setCube(x); :};
slicer_def ::= /* empty */ {: pQuery.slicer = null; :}
| WHERE expression:x {: pQuery.slicer = x; :};
cell_prop_def ::= /* empty */ {: pQuery.cellProps.clear() ; :}
| CELL PROPERTIES cell_prop_list;
cell_prop_list ::= identifier:id {: pQuery.cellProps.add(new CompoundId(id)); :}
| identifier:id {: pQuery.cellProps.add(new CompoundId(id)); :}
COMMA cell_prop_list:cl;
formula_spec ::= single_formula_spec:e
{: RESULT = new ArrayList(); RESULT.add(e); :}
| single_formula_spec:hd formula_spec:tl {: tl.add(0, hd); RESULT = tl; :};
single_formula_spec ::= member_spec:m {: RESULT = m; :}
| set_spec:s {: RESULT = s; :};
member_spec ::=
MEMBER compound_id:m AS QUOTE value_expression:e QUOTE comma_member_property_def_list_opt:l
{: RESULT = new Formula(m.toStringArray(), e, (MemberProperty[]) l.toArray(new MemberProperty[0])); :}
| MEMBER compound_id:m AS value_expression:e comma_member_property_def_list_opt:l
{: RESULT = new Formula(m.toStringArray(), e, (MemberProperty[]) l.toArray(new MemberProperty[0])); :};
comma_member_property_def_list_opt ::= /* empty */ {:RESULT = new ArrayList(); :}
| COMMA member_property_def_list:l {: RESULT = l; :};
member_property_def_list ::= member_property_definition:m
{: RESULT = new ArrayList(); RESULT.add(m); :}
| member_property_definition:hd COMMA member_property_def_list:tl
{: RESULT = tl; RESULT.add(0, hd); :};
member_property_definition ::= identifier:id EQ value_expression:e
{: RESULT = new MemberProperty(id, e); :};
set_spec ::= SET compound_id:s AS QUOTE expression:e QUOTE
{: RESULT = new Formula(s.toStringArray(), e); :}
| SET compound_id:s AS expression:e {:RESULT = new Formula(s.toStringArray(), e); :};
compound_id ::= identifier:i {: RESULT = new CompoundId(i); :}
| compound_id:hd DOT identifier:tl
{: hd.append(tl); RESULT = hd; :};
identifier ::= ID:x {: RESULT=x; :}
| QUOTED_ID:y {: RESULT=y; :};
expression ::= expression:x COLON value_expression:y
{: // range yields set
RESULT = new FunCall(":", new Exp[] { x, y }, FunCall.TypeInfix);
:}
| value_expression:v {: RESULT = v; :};
exp_list_opt ::= /* empty */ {:RESULT = new ArrayList(); :}
| exp_list:x {: RESULT=x; :};
exp_list ::= expression:e {: RESULT = new ArrayList(); RESULT.add(e); :}
| expression:e COMMA exp_list:list {: list.add(0, e); RESULT = list; :};
value_expression ::= term5:t {: RESULT = t; :}
| value_expression:x OR term5:y
{: RESULT = new FunCall("OR", new Exp[] { x, y }, FunCall.TypeInfix); :}
| value_expression:x XOR term5:y
{: RESULT = new FunCall("XOR", new Exp[] { x, y }, FunCall.TypeInfix); :};
term5 ::= term4:t {: RESULT = t; :}
| term5:x AND term4:y
{: RESULT = new FunCall("AND", new Exp[] { x, y }, FunCall.TypeInfix); :};
term4 ::= term3:t {: RESULT = t; :}
| NOT term4:p
{: RESULT = new FunCall("NOT", new Exp[] { p }, FunCall.TypePrefix); :};
term3 ::= term2:t {: RESULT = t; :}
| term3:x comp_op:op term2:y
{: RESULT = new FunCall(op, new Exp[] { x, y }, FunCall.TypeInfix); :}; // e.g. 1 < 5
term2 ::= term:t {: RESULT = t; :}
| term2:x PLUS term:y
{: RESULT = new FunCall("+", new Exp[] { x, y }, FunCall.TypeInfix); :}
| term2:x MINUS term:y
{: RESULT = new FunCall("-", new Exp[] { x, y }, FunCall.TypeInfix); :}
| term2:x CONCAT term:y
{: RESULT = new FunCall("||", new Exp[] { x, y }, FunCall.TypeInfix); :};
term ::= factor:t {: RESULT = t; :}
| term:x ASTERISK factor:y
{: RESULT = new FunCall("*", new Exp[] { x, y }, FunCall.TypeInfix); :}
| term:x SOLIDUS factor:y
{: RESULT = new FunCall("/", new Exp[] { x, y }, FunCall.TypeInfix); :};
factor ::= value_expression_primary:t {: RESULT = t; :}
| PLUS value_expression_primary:p
{: RESULT = p; :}
| MINUS value_expression_primary:p
{: RESULT = new FunCall("-", new Exp[] { p }, FunCall.TypePrefix); :};
value_expression_primary ::= STRING:s
{: RESULT = Literal.createString(s); :}
| NUMBER:d {: RESULT = Literal.create(d); :}
| identifier:i {: RESULT = new CompoundId(i); :}
| value_expression_primary:i DOT ID:j
{: RESULT = new FunCall(j, new Exp[] { i }, FunCall.TypeProperty); :}
| value_expression_primary:i DOT QUOTED_ID:j
{:
if (i instanceof CompoundId) {
((CompoundId) i).append(j);
RESULT = i;
} else {
RESULT = new FunCall(j, new Exp[] { i }, FunCall.TypePropertyQuoted);
}
:}
| value_expression_primary:i DOT AMP_QUOTED_ID:j
{:
if (i instanceof CompoundId) {
((CompoundId) i).append(j, true);
RESULT = i;
} else {
RESULT = new FunCall(j, new Exp[] { i }, FunCall.TypePropertyAmpQuoted);
}
:}
| value_expression_primary:i DOT identifier:j LPAREN exp_list_opt:lis RPAREN
{: lis.add(0, i); RESULT = new FunCall(j, (Exp[]) lis.toArray(new Exp[0]), FunCall.TypeMethod); :}
| identifier:i LPAREN exp_list_opt:lis RPAREN
{: RESULT = new FunCall(i, (Exp[]) lis.toArray(new Exp[0]), FunCall.TypeFunction); :}
| LPAREN exp_list:lis RPAREN
{:
// Whereas ([Sales],[Time]) and () are tuples, ([Sales]) and (5)
// are just expressions.
RESULT = new FunCall("()", (Exp[]) lis.toArray(new Exp[0]), FunCall.TypeParentheses);
:}
| LBRACE exp_list_opt:lis RBRACE
{: // set built from sets/tuples
RESULT = new FunCall("{}", (Exp[]) lis.toArray(new Exp[0]), FunCall.TypeBraces);
:}
| case_expression;
case_expression ::= CASE value_expression_opt:x when_list:y else_clause_opt:z END
{: ArrayList v = new ArrayList();
if (x != null) {
v.add(x);
}
for (int i = 0; i < y.size(); i++) {
Exp[] exps = (Exp[]) y.get(i);
// Util.assertTrue(exps.length == 2);
v.add(exps[0]);
v.add(exps[1]);
}
if (z != null) {
v.add(z);
}
if (x == null) {
RESULT = new FunCall("_CaseTest", (Exp[]) v.toArray(new Exp[0]), FunCall.TypeCase);
} else {
RESULT = new FunCall("_CaseMatch", (Exp[]) v.toArray(new Exp[0]), FunCall.TypeCase);
}
:};
value_expression_opt ::= /* empty */
| value_expression;
when_list ::= /* empty */ {:RESULT = new ArrayList(); :}
| when_list:x when_clause:y {: RESULT = x; x.add(y); :};
when_clause ::= WHEN value_expression:x THEN value_expression:y
{: RESULT = new Exp[] { x, y }; :};
else_clause_opt ::= /* empty */
| ELSE value_expression:x {: RESULT = x; :};
comp_op ::=
EQ {: RESULT = "="; :}
| NE {: RESULT = "<>"; :}
| LT {: RESULT = "<"; :}
| GT {: RESULT = ">"; :}
| LE {: RESULT = "<="; :}
| GE {: RESULT = ">="; :}
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -