[MRQL-96] Develop a MRQL debugger
diff --git a/core/src/main/java/org/apache/mrql/Bag.java b/core/src/main/java/org/apache/mrql/Bag.java
index 7a8acec..33424d0 100644
--- a/core/src/main/java/org/apache/mrql/Bag.java
+++ b/core/src/main/java/org/apache/mrql/Bag.java
@@ -87,6 +87,8 @@
mode = Modes.STREAMED;
iterator = i;
consumed = false;
+ if (Config.debug)
+ materialize();
}
/** is the Bag stored in an ArrayList? */
diff --git a/core/src/main/java/org/apache/mrql/Debugger.gen b/core/src/main/java/org/apache/mrql/Debugger.gen
new file mode 100644
index 0000000..266594d
--- /dev/null
+++ b/core/src/main/java/org/apache/mrql/Debugger.gen
@@ -0,0 +1,282 @@
+/**
+ * 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;
+
+import org.apache.mrql.gen.*;
+import java.util.Enumeration;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.JTree.*;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+
+
+/* The MRQL debugger that uses the lineage generated in Provenance.gen */
+public class Debugger extends JPanel implements TreeSelectionListener {
+ final MRData result;
+ final JTree tree;
+ final JTextField search = new JTextField(20);
+ private static volatile boolean exit = false;
+ Trees exprs;
+
+ /** wrapped strings to be colored red */
+ private final static class TaggedString {
+ public String value;
+ TaggedString ( String value ) { this.value = value; }
+ public String toString () { return value; }
+ }
+
+ public Debugger ( MRData result_value, Trees exprs ) {
+ super(new GridLayout(1,0));
+ result = result_value;
+ this.exprs = exprs;
+ JToolBar toolBar = new JToolBar("");
+ toolBar.setPreferredSize(new Dimension(1000,40));
+ JButton button = new JButton();
+ button.setActionCommand("Previous");
+ button.setText("prev");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed ( ActionEvent e ) {
+ }
+ });
+ button.setVisible(false);
+ toolBar.add(button);
+ button = new JButton();
+ button.setActionCommand("Next");
+ button.setText("next");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed ( ActionEvent e ) {
+ }
+ });
+ button.setVisible(false);
+ toolBar.add(button);
+ toolBar.add(Box.createRigidArea(new Dimension(400,0)));
+ button = new JButton();
+ button.setActionCommand("Clear");
+ button.setText("clear");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed ( ActionEvent e ) {
+ search.setText("");
+ DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+ DefaultMutableTreeNode root = createNode(result,"","");
+ root.setUserObject("results");
+ model.setRoot(root);
+ model.reload(root);
+ }
+ });
+ toolBar.add(button);
+ toolBar.add(search);
+ button = new JButton();
+ button.setActionCommand("SearchOutput");
+ button.setText("Search Output");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed ( ActionEvent e ) {
+ if (!search.getText().equals("")) {
+ DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+ DefaultMutableTreeNode root = createNode(result,search.getText(),"");
+ root.setUserObject("search output results");
+ model.setRoot(root);
+ model.reload(root);
+ }
+ }
+ });
+ toolBar.add(button);
+ button = new JButton();
+ button.setActionCommand("SearchInput");
+ button.setText("Search Input");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed ( ActionEvent e ) {
+ if (!search.getText().equals("")) {
+ DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+ DefaultMutableTreeNode root = createNode(result,"",search.getText());
+ root.setUserObject("search input results");
+ model.setRoot(root);
+ model.reload(root);
+ }
+ }
+ });
+ toolBar.add(button);
+ tree = new JTree(createNode(result,"",""));
+ JScrollPane sp = new JScrollPane(tree,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ sp.setPreferredSize(new Dimension(1000,2000));
+ sp.getVerticalScrollBar().setPreferredSize(new Dimension(20,0));
+ tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+ Font currentFont = tree.getFont();
+ tree.setFont(new Font(currentFont.getName(),
+ currentFont.getStyle(),
+ (int)(currentFont.getSize()*1.5)));
+ DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
+ public Component getTreeCellRendererComponent
+ ( JTree tree, Object value, boolean sel, boolean exp,
+ boolean leaf, int row, boolean hasFocus ) {
+ super.getTreeCellRendererComponent(tree,value,sel,exp,leaf,row,hasFocus);
+ // tagged strings are red
+ if (((DefaultMutableTreeNode)value).getUserObject() instanceof TaggedString)
+ setForeground(Color.red);
+ return this;
+ }
+ };
+ renderer.setLeafIcon(null);
+ renderer.setOpenIcon(null);
+ renderer.setClosedIcon(null);
+ tree.setCellRenderer(renderer);
+ tree.addTreeSelectionListener(this);
+ setLayout(new BorderLayout());
+ add(toolBar,BorderLayout.NORTH);
+ add(sp,BorderLayout.CENTER);
+ }
+
+ public void valueChanged ( TreeSelectionEvent e ) { }
+
+ private String exprNode ( Tree e ) {
+ match e {
+ case call(source,_,`path,...):
+ return "source: "+path;
+ case call(`f,...):
+ return f.toString();
+ case cmap(lambda(`v,_),_):
+ return "cmap "+v;
+ case groupBy(_):
+ return "groupBy";
+ case coGroup(...):
+ return "coGroup";
+ case reduce(`m,...):
+ return "reduce("+m+")";
+ case project(`v,`a):
+ return exprNode(v)+"."+a;
+ case nth(`x,`n):
+ return exprNode(x)+"#"+n;
+ case `f(...):
+ return f;
+ };
+ return e.toString();
+ }
+
+ private DefaultMutableTreeNode create_node ( MRData value, int n, String inputSearch ) {
+ if (value instanceof Tuple) {
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode("input "+n);
+ DefaultMutableTreeNode child = provenanceNode(value,inputSearch);
+ if (child.getUserObject() instanceof TaggedString)
+ node.setUserObject(new TaggedString("input "+n));
+ node.add(child);
+ return node;
+ } else if (value instanceof Bag) {
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode("input "+n);
+ boolean matched = false;
+ for ( MRData e: (Bag)value ) {
+ DefaultMutableTreeNode child = provenanceNode(e,inputSearch);
+ matched |= child.getUserObject() instanceof TaggedString;
+ node.add(child);
+ };
+ if (matched)
+ node.setUserObject(new TaggedString("input "+n));
+ return node;
+ } else return new DefaultMutableTreeNode(value.toString());
+ }
+
+ private DefaultMutableTreeNode provenanceNode ( MRData value, String inputSearch ) {
+ Tuple p = ((Tuple)value);
+ MRData v = p.get(1);
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode(v.toString());
+ Tree opr = exprs.nth(((MR_int)p.get(0)).get());
+ node.add(new DefaultMutableTreeNode(exprNode(opr)));
+ boolean matched = false;
+ for ( int i = 2; i < p.size(); i++ ) {
+ DefaultMutableTreeNode child = create_node(p.get(i),i-1,inputSearch);
+ node.add(child);
+ matched |= child.getUserObject() instanceof TaggedString;
+ };
+ if (matched)
+ node.setUserObject(new TaggedString(v.toString()));
+ else match opr {
+ case call(source,...):
+ if (!inputSearch.equals("") && v.toString().contains(inputSearch))
+ node.setUserObject(new TaggedString(v.toString()));
+ };
+ return node;
+ }
+
+ private DefaultMutableTreeNode createNode ( MRData value, String outputSearch, String inputSearch ) {
+ if (value instanceof Bag) {
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode("results");
+ for ( MRData e: (Bag)value )
+ if (outputSearch.equals("") || ((Tuple)e).get(0).toString().contains(outputSearch)) {
+ DefaultMutableTreeNode child = provenanceNode(((Tuple)e).get(1),inputSearch);
+ if (inputSearch.equals("") || (child.getUserObject() instanceof TaggedString))
+ node.add(child);
+ };
+ return node;
+ } else if (value instanceof MR_dataset) {
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode("results");
+ for ( MRData e: ((MR_dataset)value).dataset().take(Config.max_bag_size_print) )
+ if (outputSearch.equals("") || ((Tuple)e).get(0).toString().contains(outputSearch)) {
+ DefaultMutableTreeNode child = provenanceNode(((Tuple)e).get(1),inputSearch);
+ if (inputSearch.equals("") || (child.getUserObject() instanceof TaggedString))
+ node.add(child);
+ };
+ return node;
+ } else {
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode(((Tuple)value).get(0).toString());
+ node.add(provenanceNode(((Tuple)value).get(1),inputSearch));
+ return node;
+ }
+ }
+
+ private static void createAndShowGUI ( MRData lineage, Tree tp, Trees exprs ) {
+ final JFrame frame = new JFrame("MRQL debugger");
+ frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ frame.addWindowListener(new WindowListener() {
+ public void windowClosing ( WindowEvent e ) {
+ frame.setVisible(false);
+ frame.dispose();
+ exit = true;
+ }
+ public void windowActivated ( WindowEvent e ) {}
+ public void windowClosed ( WindowEvent e ) {}
+ public void windowDeactivated ( WindowEvent e ) {}
+ public void windowDeiconified ( WindowEvent e ) {}
+ public void windowIconified ( WindowEvent e ) {}
+ public void windowOpened ( WindowEvent e ) {}
+ });
+ frame.add(new Debugger(lineage,exprs));
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ /** use the MRQL debugger on a query result
+ * @param lineage the query result extended with lineage
+ * @param type the result type
+ * @param exprs the expr terms used in the lineage
+ */
+ public static void debug ( final MRData lineage, final Tree type, final Trees exprs ) {
+ try {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run () {
+ createAndShowGUI(lineage,type,exprs);
+ }
+ });
+ exit = false;
+ while (!exit)
+ Thread.sleep(1000);
+ } catch (Exception ex) {
+ }
+ }
+}
diff --git a/core/src/main/java/org/apache/mrql/Interpreter.gen b/core/src/main/java/org/apache/mrql/Interpreter.gen
index e7dac63..37e2147 100644
--- a/core/src/main/java/org/apache/mrql/Interpreter.gen
+++ b/core/src/main/java/org/apache/mrql/Interpreter.gen
@@ -28,6 +28,7 @@
public class Interpreter extends TypeInference {
public final static Tree identity_mapper = #<lambda(x,bag(x))>;
+ public static boolean debug_mode = false;
protected static Environment global_env = null;
@@ -615,13 +616,17 @@
return new Bag();
case provenance(`x,`tp,...s):
MRData value = evalE(x,env);
- Provenance.display(value,tp,#[...s]);
+ if (Config.debug)
+ Debugger.debug(value,tp,#[...s]);
+ else Provenance.display(value,tp,#[...s]);
return new Tuple(0);
case Provenance(`x,`tp,...s):
MRData value = (Config.hadoop_mode)
? new MR_dataset(Evaluator.evaluator.eval(x,env,"-"))
: evalS(x,env);
- Provenance.display(value,tp,#[...s]);
+ if (Config.debug)
+ Debugger.debug(value,tp,#[...s]);
+ else Provenance.display(value,tp,#[...s]);
return new Tuple(0);
case Lineage(...as):
return evalEE(#<tuple(...as)>,env);
@@ -914,7 +919,7 @@
if (Config.trace)
System.out.println("After provenance injection:\n"+ne.pretty(0));
} else if (Config.debug) {
- ne = Provenance.embed_provenance(ne,true);
+ ne = Provenance.embed_provenance(ne,debug_mode);
if (Config.trace)
System.out.println("After provenance injection:\n"+ne.pretty(0));
};
diff --git a/core/src/main/java/org/apache/mrql/Provenance.gen b/core/src/main/java/org/apache/mrql/Provenance.gen
index 513d629..62cae72 100644
--- a/core/src/main/java/org/apache/mrql/Provenance.gen
+++ b/core/src/main/java/org/apache/mrql/Provenance.gen
@@ -57,7 +57,7 @@
}
/** The nodes of the query AST */
- private static Trees exprs = #[];
+ static Trees exprs = #[];
/** Construct a provenance tuple
* @param expr the AST that corresponds to this value
@@ -68,6 +68,8 @@
private static Tree prov ( Tree expr, Tree value, Trees provenance ) {
exprs = exprs.append(expr);
int loc = exprs.length()-1;
+ if (value.is_variable())
+ return #<tuple(`value,Lineage(`loc,`value,...provenance))>;
Tree nv = new_var();
return #<let(`nv,`value,tuple(`nv,Lineage(`loc,`nv,...provenance)))>;
}
@@ -111,13 +113,11 @@
Tree nw = new_var();
Tree ex = embedB(x);
Tree nb = subst(v,#<nth(`nv,0)>,b);
- return #<cmap(lambda(`nv,cmap(lambda(`nw,bag(tuple(`nw,nth(`nv,1)))),
- `nb)),
- `ex)>;
+ Tree p = prov(e,nw,#<nth(`nv,1)>);
+ return #<cmap(lambda(`nv,cmap(lambda(`nw,bag(`p)),`nb)),`ex)>;
case cmap(lambda(`v,`b),`x):
Tree nv = new_var();
Tree nw = new_var();
- Tree y = new_var();
Tree ex = embedB(x);
Tree ef = lift_var(v,nv,#<nth(`nv,0)>,embedB(b));
Tree p = prov(e,#<nth(`nw,0)>,#<nth(`nw,1)>);
@@ -136,13 +136,15 @@
return #<cmap(lambda(`nv,bag(`p)),orderBy(`ex))>;
case coGroup(`x,`y):
Tree nv = new_var();
+ Tree xv = new_var();
+ Tree yv = new_var();
Tree ex = flip(embedB(x));
Tree ey = flip(embedB(y));
- Tree val = #<tuple(nth(`nv,0),tuple(`(first(#<nth(nth(`nv,1),0)>)),
- `(first(#<nth(nth(`nv,1),1)>))))>;
- Tree p = prov(e,val,#[`(second(#<nth(nth(`nv,1),0)>)),
- `(second(#<nth(nth(`nv,1),1)>))]);
- return #<cmap(lambda(`nv,bag(`p)),coGroup(`ex,`ey))>;
+ Tree val = #<tuple(nth(`nv,0),tuple(`(first(xv)),`(first(yv))))>;
+ Tree p = prov(e,val,#[`(second(xv)),`(second(yv))]);
+ return #<cmap(lambda(`nv,bag(let(`xv,nth(nth(`nv,1),0),
+ let(`yv,nth(nth(`nv,1),1),`p)))),
+ coGroup(`ex,`ey))>;
case call(source,...):
Tree nv = new_var();
Tree p = prov(e,nv,#[ ]);
@@ -196,12 +198,22 @@
/** Lift the expression e of type t to (t,provenance) */
public static Tree embedP ( Tree e ) {
+ match TypeInference.type_inference(e) {
+ case `T(_):
+ if (!is_collection(T))
+ fail;
+ Tree nv = new_var();
+ Tree ex = embedB(e);
+ Tree p = prov(e,first(nv),second(nv));
+ return #<let(`nv,`ex,`p)>;
+ };
match e {
case reduce(`m,`x):
Tree nv = new_var();
Tree ex = embedB(x);
Tree p = prov(e,#<reduce(`m,`(first(nv)))>,second(nv));
- return #<Let(`nv,`ex,`p)>;
+ return #<let(`nv,`ex,`p)>;
+ //return #<Let(`nv,`ex,`p)>;
case tuple(...as):
Tree nv = new_var();
Trees es = #[ ];
@@ -277,15 +289,6 @@
return prov(e,e,#[ ]);
else return v;
};
- match TypeInference.type_inference(e) {
- case `T(_):
- if (!is_collection(T))
- fail;
- Tree nv = new_var();
- Tree ex = embedB(e);
- Tree p = prov(e,first(nv),second(nv));
- return #<Let(`nv,`ex,`p)>;
- };
return prov(e,e,#[ ]);
}
@@ -328,21 +331,20 @@
Bag s = new Bag();
for ( int i = 2; i < p.size() && s.size() < Config.max_bag_size_print; i++ )
for ( MRData e: collect_lineage(p.get(i)) )
- if (!member(s,e))
- s.add(e);
+ s.add(e);
return s;
} else if (value instanceof Bag) {
Bag s = new Bag();
((Bag)value).materialize();
for ( MRData e: (Bag)value )
for ( MRData x: collect_lineage(e) )
- if (s.size() < Config.max_bag_size_print && !member(s,x))
+ if (s.size() < Config.max_bag_size_print)
s.add(x);
return s;
} else return new Bag();
}
- /** Print the the data sources that contribute to the output to the output */
+ /** Print the data sources that contribute to the output */
public static void display ( MRData value, Tree tp, Trees prov_exprs ) {
exprs = prov_exprs;
match tp {
diff --git a/core/src/main/java/org/apache/mrql/Streaming.gen b/core/src/main/java/org/apache/mrql/Streaming.gen
index 53034a9..c4ff10f 100644
--- a/core/src/main/java/org/apache/mrql/Streaming.gen
+++ b/core/src/main/java/org/apache/mrql/Streaming.gen
@@ -854,15 +854,13 @@
Tree vy = new_var();
Tree cx = convert_to_algebra(x);
Tree cy = convert_to_algebra(y);
- Tree mx = new_var();
- Tree my = new_var();
return #<join(lambda(`vx,nth(`vx,0)),lambda(`vy,nth(`vy,0)),
lambda(`v,bag(tuple(call(join_key,nth(`v,0),nth(`v,1)),
tuple(cmap(lambda(`vx,bag(nth(`vx,1))),nth(`v,0)),
cmap(lambda(`vy,bag(nth(`vy,1))),nth(`v,1)))))),
`cx, `cy)>;
- case reduce(`aggr,`s):
- return convert_reduce(aggr,convert_to_algebra(s));
+ case reduce(`aggr,`s):
+ return convert_reduce(aggr,convert_to_algebra(s));
case `f(...as):
Trees bs = #[ ];
for ( Tree a: as )
diff --git a/core/src/main/java/org/apache/mrql/TopLevel.gen b/core/src/main/java/org/apache/mrql/TopLevel.gen
index 769099a..b4f1c3a 100644
--- a/core/src/main/java/org/apache/mrql/TopLevel.gen
+++ b/core/src/main/java/org/apache/mrql/TopLevel.gen
@@ -379,23 +379,25 @@
};
case lineage(`e):
Config.lineage = true;
- boolean quiet = Config.quiet_execution;
- Config.quiet_execution = true;
+ if (Config.hadoop_mode)
+ Config.write(Plan.conf);
long t = System.currentTimeMillis();
if (expression(e,false) != null && !Config.quiet_execution)
System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
- Config.lineage = false;
- Config.quiet_execution = quiet;
- case debug(`path,`e):
+ if (Config.hadoop_mode)
+ Config.write(Plan.conf);
+ case debug(`mode,`e):
Config.debug = true;
boolean quiet = Config.quiet_execution;
Config.quiet_execution = true;
- long t = System.currentTimeMillis();
- dump(path.stringValue(),e);
- if (!Config.quiet_execution)
- System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
+ if (Config.hadoop_mode)
+ Config.write(Plan.conf);
+ debug_mode = mode.equals(#<fine>);
+ expression(e,false);
Config.debug = false;
Config.quiet_execution = quiet;
+ if (Config.hadoop_mode)
+ Config.write(Plan.conf);
case dump(`s,`e):
long t = System.currentTimeMillis();
dump(s.stringValue(),e);
diff --git a/core/src/main/java/org/apache/mrql/mrql.cgen b/core/src/main/java/org/apache/mrql/mrql.cgen
index 6e09902..795243a 100644
--- a/core/src/main/java/org/apache/mrql/mrql.cgen
+++ b/core/src/main/java/org/apache/mrql/mrql.cgen
@@ -35,7 +35,7 @@
sym.STEP, sym.LIMIT, sym.LET, sym.ATSYM, sym.EXCLAMATION,
sym.Variable, sym.Integer, sym.Double, sym.String, sym.Decimal,
sym.START_TEMPLATE, sym.END_TEMPLATE, sym.TEXT, sym.TRACE, sym.INCR,
- sym.LINEAGE, sym.DEBUG
+ sym.LINEAGE, sym.DEBUG, sym.DEBUGALL
};
static String[] token_names = {
@@ -51,7 +51,7 @@
"step", "limit", "let", "@", "!",
"Variable", "Integer", "Double", "String", "Decimal",
"[|", "|]", "Text", "trace", "incr",
- "lineage", "debug"
+ "lineage", "debug", "debug all"
};
public static String print ( Symbol s ) {
@@ -101,7 +101,7 @@
ORDER, GROUP, BY, ASCENDING, DESCENDING, UMINUS, FUNCTION, DISTINCT, BSLASH,
SOME, ALL, GTR, SEP, STORE, TYPE, DATA, CASE, ATSYM, XPATH, REPEAT, STEP, LIMIT,
LET, IMPORT, PARSER, AGGREGATION, INCLUDE, EXCLAMATION, MACRO, DUMP, TRACE, INCR,
- LINEAGE, DEBUG;
+ LINEAGE, DEBUG, DEBUGALL;
terminal String Variable;
terminal Long Integer;
@@ -147,7 +147,8 @@
| DUMP String:s FROM expr:e {: RESULT = #<dump_text(`(new StringLeaf(s)),`e)>; :}
| INCR expr:e {: RESULT = #<incr(`e)>; :}
| LINEAGE expr:e {: RESULT = #<lineage(`e)>; :}
- | DEBUG String:s expr:e {: RESULT = #<debug(`s,`e)>; :}
+ | DEBUG expr:e {: RESULT = #<debug(coarse,`e)>; :}
+ | DEBUGALL expr:e {: RESULT = #<debug(fine,`e)>; :}
| TYPE var:v EQ type:t {: RESULT = #<typedef(`v,`t)>; :}
| DATA var:v EQ data_binds:nl {: RESULT = #<datadef(`v,union(...nl))>; :}
| FUNCTION var:f LP
diff --git a/core/src/main/java/org/apache/mrql/mrql.lex b/core/src/main/java/org/apache/mrql/mrql.lex
index 868eb05..39cd33d 100644
--- a/core/src/main/java/org/apache/mrql/mrql.lex
+++ b/core/src/main/java/org/apache/mrql/mrql.lex
@@ -186,6 +186,7 @@
<YYINITIAL> "trace" { return symbol(sym.TRACE); }
<YYINITIAL> "lineage" { return symbol(sym.LINEAGE); }
<YYINITIAL> "debug" { return symbol(sym.DEBUG); }
+<YYINITIAL> "debug all" { return symbol(sym.DEBUGALL); }
<YYINITIAL> {ID} { return symbol(sym.Variable,yytext()); }