blob: 91432ba8f89c6fed9b9e395bfb90412564e34872 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.mrql.gen;
import java_cup.runtime.*;
import java.util.Stack;
parser code {:
static int[] tokens = {
GenSym.error, GenSym.CHAR, GenSym.ID, GenSym.CSTRING, GenSym.LONG, GenSym.DOUBLE,
GenSym.META, GenSym.MATCH, GenSym.CASE, GenSym.IS, GenSym.COLON, GenSym.COMMA,
GenSym.GT, GenSym.LP, GenSym.RP, GenSym.LB, GenSym.RB, GenSym.LSB, GenSym.RSB,
GenSym.BQ, GenSym.BQP, GenSym.DOTSP, GenSym.ANY, GenSym.OPER, GenSym.FAIL
};
static String[] token_names = {
"error", "character", "identifier", "string", "integer", "float",
"#<", "match", "case", "is", ":", ",", ">", "(", ")", "[", "]", "{", "}",
"`", "`(", "...(", "_", "operator", "fail"
};
public static String print ( Symbol s ) {
for (int i=0; i<tokens.length; i++)
if (tokens[i]==s.sym)
{ String res = token_names[i] + " ";
if (s.value==null)
return res;
else if (s.value instanceof Long)
return res + ((Long) s.value).longValue();
else if (s.value instanceof Double)
return res + ((Double) s.value).doubleValue();
else if (s.value instanceof String)
return res + (String) s.value;
}
return "?";
}
public static java.io.PrintStream out;
public static GenLex scanner;
public static Tree parse_tree;
public static int newlines = 0;
public static int lcase = 0;
public static Stack<String> labels = new Stack<String>();
public void syntax_error ( Symbol token ) {
throw new Error("*** Syntax Error: " + print(token) + " (line: " + scanner.line_pos()
+ ", position: " + scanner.char_pos() + ")");
}
:};
/* Terminals (tokens returned by the scanner). */
terminal META, METAL, MATCH, CASE, FAIL, IS, DOTS, COLON, COMMA, GT, LP, RP, LB, RB, LSB, RSB, BQ, BQP, DOTSP, ANY;
terminal String CHAR;
terminal String ID;
terminal Long LONG;
terminal Double DOUBLE;
terminal String CSTRING;
terminal String OPER;
non terminal Tree exp, name, variable, rest;
non terminal Trees expl;
non terminal String case, cases, schar, jcode, scode;
non terminal pcode, prog;
precedence left OPER;
precedence nonassoc META;
precedence nonassoc MATCH;
precedence nonassoc CASE;
precedence nonassoc CSTRING;
precedence nonassoc CHAR;
start with prog;
prog ::= pcode
;
pcode ::= scode:s {: parser.out.print(s); :}
| pcode scode:s {: parser.out.print(s); :}
;
jcode ::= scode:s {: RESULT = s; :}
| jcode:c scode:s {: RESULT = c+s; :}
;
scode ::= schar:s {: RESULT = s; :}
| LSB RSB {: RESULT = "{}"; :}
| LSB jcode:c RSB {: RESULT = "{"+c+"}"; :}
| METAL RB {: RESULT = "Trees.nil"; :}
| META exp:e GT {: GenParser.parse_tree = e;
RESULT = Meta.reify(e);
for (int i=0; i < parser.newlines; i++)
RESULT += "\n";
parser.newlines = 0; :}
| METAL expl:r RB {: RESULT = Meta.reify(new Node("Node",
new Trees(new VariableLeaf("F"),r)));
RESULT = RESULT.substring(13,RESULT.length()-1);
for (int i=0; i < parser.newlines; i++)
RESULT += "\n";
parser.newlines = 0; :}
| MATCH {: Meta.level++;
GenLex.context.new_context();
GenLex.context.in_match_body();
:}
jcode:c LSB cases:el RSB {: RESULT = "{ boolean FOUND_" + Meta.level + " = false; Tree E_"
+ Meta.level + " = " + c + "; " + el + " }";
GenLex.context.close_context(GenParser.scanner);
for (int i=0; i < parser.newlines; i++)
RESULT += "\n";
parser.newlines = 0;
Meta.level--; :}
| FAIL {: RESULT = "{ FOUND_" + Meta.level + "=false; break " + GenParser.labels.peek() + "; }"; :}
;
schar ::= CHAR:c {: RESULT = c; :}
| CSTRING:s {: RESULT = Crypt.encrypt(s); :}
;
cases ::= jcode:j case:c {: RESULT = j+c; :}
| cases:cl case:c {: RESULT = cl + " if (!FOUND_" + Meta.level + ") " + c; :}
;
case ::= CASE {: GenParser.labels.push("LCASE_"+GenParser.lcase++); :}
exp:e COLON jcode:j {: Condition m = Meta.pattern(e,"E_" + Meta.level);
RESULT = "{ " + GenParser.labels.pop() + ": ";
RESULT += (m.pred.equals("true")) ? "" : "if (" + m.pred + ") ";
for (int i=0; i < parser.newlines; i++)
RESULT += "\n";
parser.newlines = 0;
RESULT += "{ " + m.stmt + " FOUND_" + Meta.level
+ "=true; " + j + " }";
for (int i = 0; i <= m.unmatched_brackets; i++)
RESULT += "}";
RESULT += ";"; :}
;
name ::= ID:s {: RESULT = new VariableLeaf(s); :}
;
variable ::= name:s {: RESULT = s; :}
| BQ name:s {: RESULT = new Node("Escape",new Trees(s)); :}
| BQP jcode:c RP {: RESULT = new Node("Code",new Trees(new StringLeaf(c))); :}
| ANY {: RESULT = new VariableLeaf("_any_"); :}
;
exp ::= LONG:n {: RESULT = new LongLeaf(n.longValue()); :}
| DOUBLE:n {: RESULT = new DoubleLeaf(n.doubleValue()); :}
| CSTRING:s {: RESULT = new StringLeaf(s); :}
| variable:e {: RESULT = e; :}
| variable:e LP RP {: RESULT = new Node("Node",new Trees(e)); :}
| variable:e LP expl:el RP {: RESULT = new Node("Node",new Trees(e,el)); :}
| BQ name:s LB exp:e RB {: RESULT = new Node("Higher",new Trees(s,new Trees(e))); :}
| name:s IS exp:e {: RESULT = new Node("IS",new Trees(s,new Trees(e))); :}
| LP exp:e RP {: RESULT = e; :}
| exp:e1 OPER:o exp:e2 {: RESULT = new Node("Node",new Trees(new VariableLeaf(o),
new Trees(e1,new Trees(e2)))); :}
;
expl ::= exp:e {: RESULT = new Trees(e); :}
| rest:e {: RESULT = new Trees(e); :}
| expl:el COMMA rest:e {: RESULT = el.append(e); :}
| expl:el COMMA exp:e {: RESULT = el.append(e); :}
;
rest ::= DOTS name:n {: RESULT = new Node("Dots",new Trees(n)); :}
| DOTSP jcode:c RP {: RESULT = new Node("Dots",new Trees(new StringLeaf(c))); :}
| DOTS {: RESULT = new Node("Dots"); :}
;