[asm asm] block fixing bugs and setting color style
This commit is contained in:
parent
47bc05f4d7
commit
2b25736cc8
|
@ -2,9 +2,7 @@ package org.ethereum.gui;
|
||||||
|
|
||||||
import org.abego.treelayout.internal.util.Contract;
|
import org.abego.treelayout.internal.util.Contract;
|
||||||
import org.ethereum.serpent.SerpentCompiler;
|
import org.ethereum.serpent.SerpentCompiler;
|
||||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
import org.fife.ui.rsyntaxtextarea.*;
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
|
||||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -46,7 +44,7 @@ public class SerpentEditor extends JFrame {
|
||||||
"return(0)\n";
|
"return(0)\n";
|
||||||
|
|
||||||
|
|
||||||
|
private final RSyntaxTextArea codeArea;
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public SerpentEditor() {
|
public SerpentEditor() {
|
||||||
|
@ -63,11 +61,12 @@ public class SerpentEditor extends JFrame {
|
||||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory)TokenMakerFactory.getDefaultInstance();
|
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory)TokenMakerFactory.getDefaultInstance();
|
||||||
atmf.putMapping("text/serpent", "org.ethereum.gui.SerpentTokenMaker");
|
atmf.putMapping("text/serpent", "org.ethereum.gui.SerpentTokenMaker");
|
||||||
|
|
||||||
final RSyntaxTextArea codeArea = new RSyntaxTextArea(32, 80);
|
codeArea = new RSyntaxTextArea(32, 80);
|
||||||
codeArea.setSyntaxEditingStyle("text/serpent");
|
codeArea.setSyntaxEditingStyle("text/serpent");
|
||||||
codeArea.setCodeFoldingEnabled(true);
|
codeArea.setCodeFoldingEnabled(true);
|
||||||
codeArea.setAntiAliasingEnabled(true);
|
codeArea.setAntiAliasingEnabled(true);
|
||||||
codeArea.setText(codeSample2);
|
codeArea.setText(codeSample2);
|
||||||
|
changeStyleProgrammatically();
|
||||||
|
|
||||||
RTextScrollPane sp = new RTextScrollPane(codeArea);
|
RTextScrollPane sp = new RTextScrollPane(codeArea);
|
||||||
|
|
||||||
|
@ -184,6 +183,33 @@ public class SerpentEditor extends JFrame {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void changeStyleProgrammatically() {
|
||||||
|
|
||||||
|
// Set the font for all token types.
|
||||||
|
|
||||||
|
// Change a few things here and there.
|
||||||
|
SyntaxScheme scheme = codeArea.getSyntaxScheme();
|
||||||
|
|
||||||
|
// scheme.getStyle(Token.RESERVED_WORD).background = Color.white;
|
||||||
|
// scheme.getStyle(Token.RESERVED_WORD).foreground = Color.BLUE;
|
||||||
|
|
||||||
|
scheme.getStyle(Token.IDENTIFIER).foreground = Color.black;
|
||||||
|
|
||||||
|
|
||||||
|
scheme.getStyle(Token.RESERVED_WORD_2).background = Color.white;
|
||||||
|
scheme.getStyle(Token.RESERVED_WORD_2).foreground = Color.MAGENTA.darker().darker();
|
||||||
|
|
||||||
|
|
||||||
|
// scheme.getStyle(Token.LITERAL_STRING_DOUBLE_QUOTE).underline = true;
|
||||||
|
// scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).underline = true;
|
||||||
|
// scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).background = Color.pink;
|
||||||
|
|
||||||
|
// scheme.getStyle(Token.COMMENT_EOL).font = new Font("Georgia", Font.ITALIC, 10);
|
||||||
|
|
||||||
|
codeArea.revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Start all Swing applications on the EDT.
|
// Start all Swing applications on the EDT.
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.ethereum.gui;
|
||||||
|
|
||||||
import javax.swing.text.Segment;
|
import javax.swing.text.Segment;
|
||||||
|
|
||||||
|
import org.ethereum.vm.OpCode;
|
||||||
import org.fife.ui.rsyntaxtextarea.*;
|
import org.fife.ui.rsyntaxtextarea.*;
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ public class SerpentTokenMaker extends AbstractTokenMaker {
|
||||||
@Override
|
@Override
|
||||||
public TokenMap getWordsToHighlight() {
|
public TokenMap getWordsToHighlight() {
|
||||||
|
|
||||||
TokenMap tokenMap = new TokenMap(true); // Ignore case.
|
TokenMap tokenMap = new TokenMap(false); // Ignore case.
|
||||||
|
|
||||||
int reservedWord = Token.RESERVED_WORD;
|
int reservedWord = Token.RESERVED_WORD;
|
||||||
tokenMap.put("set", reservedWord);
|
tokenMap.put("set", reservedWord);
|
||||||
|
@ -135,6 +136,13 @@ public class SerpentTokenMaker extends AbstractTokenMaker {
|
||||||
tokenMap.put("block", function);
|
tokenMap.put("block", function);
|
||||||
tokenMap.put("tx", function);
|
tokenMap.put("tx", function);
|
||||||
|
|
||||||
|
// ALL the assembly tokens
|
||||||
|
int reservedWord2 = Token.RESERVED_WORD_2;
|
||||||
|
for (OpCode value : OpCode.values()){
|
||||||
|
tokenMap.put(value.name(), reservedWord2);
|
||||||
|
tokenMap.put("[asm", reservedWord2);
|
||||||
|
tokenMap.put("asm]", reservedWord2);
|
||||||
|
}
|
||||||
|
|
||||||
return tokenMap;
|
return tokenMap;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ parse: block EOF
|
||||||
block: ( asm | assign | special_func | if_elif_else_stmt | while_stmt | ret_func | msg_func)* ;
|
block: ( asm | assign | special_func | if_elif_else_stmt | while_stmt | ret_func | msg_func)* ;
|
||||||
|
|
||||||
|
|
||||||
asm: '[asm' (ASM_SYMBOLS | INT)* 'asm]' NL;
|
asm: '[asm' asm_symbol 'asm]' NL;
|
||||||
|
asm_symbol: (ASM_SYMBOLS | INT)* ;
|
||||||
|
|
||||||
if_elif_else_stmt: 'if' condition ':' INDENT block DEDENT
|
if_elif_else_stmt: 'if' condition ':' INDENT block DEDENT
|
||||||
('elif' condition ':' INDENT block DEDENT)*
|
('elif' condition ':' INDENT block DEDENT)*
|
||||||
|
|
|
@ -90,6 +90,19 @@ public class SerpentBaseListener implements SerpentListener {
|
||||||
*/
|
*/
|
||||||
@Override public void exitBlock(@NotNull SerpentParser.BlockContext ctx) { }
|
@Override public void exitBlock(@NotNull SerpentParser.BlockContext ctx) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
|
@Override public void enterAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
|
@Override public void exitAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -220,19 +233,6 @@ public class SerpentBaseListener implements SerpentListener {
|
||||||
*/
|
*/
|
||||||
@Override public void exitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx) { }
|
@Override public void exitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx) { }
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
* <p/>
|
|
||||||
* The default implementation does nothing.
|
|
||||||
*/
|
|
||||||
@Override public void enterMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { }
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
* <p/>
|
|
||||||
* The default implementation does nothing.
|
|
||||||
*/
|
|
||||||
@Override public void exitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -246,6 +246,19 @@ public class SerpentBaseListener implements SerpentListener {
|
||||||
*/
|
*/
|
||||||
@Override public void exitRel_exp(@NotNull SerpentParser.Rel_expContext ctx) { }
|
@Override public void exitRel_exp(@NotNull SerpentParser.Rel_expContext ctx) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
|
@Override public void enterMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* The default implementation does nothing.
|
||||||
|
*/
|
||||||
|
@Override public void exitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
|
|
@ -60,6 +60,14 @@ public class SerpentBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
|
||||||
*/
|
*/
|
||||||
@Override public T visitBlock(@NotNull SerpentParser.BlockContext ctx) { return visitChildren(ctx); }
|
@Override public T visitBlock(@NotNull SerpentParser.BlockContext ctx) { return visitChildren(ctx); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p/>
|
||||||
|
* The default implementation returns the result of calling
|
||||||
|
* {@link #visitChildren} on {@code ctx}.
|
||||||
|
*/
|
||||||
|
@Override public T visitAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx) { return visitChildren(ctx); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -146,7 +154,7 @@ public class SerpentBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
|
||||||
* The default implementation returns the result of calling
|
* The default implementation returns the result of calling
|
||||||
* {@link #visitChildren} on {@code ctx}.
|
* {@link #visitChildren} on {@code ctx}.
|
||||||
*/
|
*/
|
||||||
@Override public T visitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { return visitChildren(ctx); }
|
@Override public T visitRel_exp(@NotNull SerpentParser.Rel_expContext ctx) { return visitChildren(ctx); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
|
@ -154,7 +162,7 @@ public class SerpentBaseVisitor<T> extends AbstractParseTreeVisitor<T> implement
|
||||||
* The default implementation returns the result of calling
|
* The default implementation returns the result of calling
|
||||||
* {@link #visitChildren} on {@code ctx}.
|
* {@link #visitChildren} on {@code ctx}.
|
||||||
*/
|
*/
|
||||||
@Override public T visitRel_exp(@NotNull SerpentParser.Rel_expContext ctx) { return visitChildren(ctx); }
|
@Override public T visitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx) { return visitChildren(ctx); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
|
|
|
@ -44,7 +44,19 @@ public class SerpentCompiler {
|
||||||
List<String> lexaList = new ArrayList<String>();
|
List<String> lexaList = new ArrayList<String>();
|
||||||
Collections.addAll(lexaList, lexaArr);
|
Collections.addAll(lexaList, lexaArr);
|
||||||
|
|
||||||
|
// temporary remove all push inserted
|
||||||
|
// by [asm asm] block
|
||||||
|
for (int i = 0; i < lexaList.size(); ++i){
|
||||||
|
|
||||||
|
String lexa = lexaList.get(i);
|
||||||
|
if (lexa.length() >= 4 && lexa.substring(0,4).equals("PUSH")){
|
||||||
|
|
||||||
|
lexaList.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Encode push_n numbers
|
// Encode push_n numbers
|
||||||
|
boolean skiping = false;
|
||||||
for (int i = 0; i < lexaList.size(); ++i){
|
for (int i = 0; i < lexaList.size(); ++i){
|
||||||
|
|
||||||
String lexa = lexaList.get(i);
|
String lexa = lexaList.get(i);
|
||||||
|
@ -53,16 +65,16 @@ public class SerpentCompiler {
|
||||||
lexa.contains("REF_") ||
|
lexa.contains("REF_") ||
|
||||||
lexa.contains("LABEL_")) continue;
|
lexa.contains("LABEL_")) continue;
|
||||||
|
|
||||||
int bytesNum = ByteUtil.numBytes( lexa );
|
int bytesNum = ByteUtil.numBytes(lexa);
|
||||||
|
|
||||||
String num = lexaList.remove(i);
|
String num = lexaList.remove(i);
|
||||||
BigInteger bNum = new BigInteger(num);
|
BigInteger bNum = new BigInteger(num);
|
||||||
byte[] bytes = BigIntegers.asUnsignedByteArray(bNum);
|
byte[] bytes = BigIntegers.asUnsignedByteArray(bNum);
|
||||||
if (bytes.length == 0)bytes = new byte[]{0};
|
if (bytes.length == 0) bytes = new byte[]{0};
|
||||||
|
|
||||||
for (int j = bytes.length; j > 0 ; --j){
|
for (int j = bytes.length; j > 0; --j) {
|
||||||
|
|
||||||
lexaList.add(i, (bytes[j-1] & 0xFF) +"");
|
lexaList.add(i, (bytes[j - 1] & 0xFF) + "");
|
||||||
}
|
}
|
||||||
|
|
||||||
lexaList.add(i, "PUSH" + bytesNum);
|
lexaList.add(i, "PUSH" + bytesNum);
|
||||||
|
|
|
@ -74,6 +74,17 @@ public interface SerpentListener extends ParseTreeListener {
|
||||||
*/
|
*/
|
||||||
void exitBlock(@NotNull SerpentParser.BlockContext ctx);
|
void exitBlock(@NotNull SerpentParser.BlockContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter a parse tree produced by {@link SerpentParser#asm_symbol}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void enterAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx);
|
||||||
|
/**
|
||||||
|
* Exit a parse tree produced by {@link SerpentParser#asm_symbol}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void exitAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enter a parse tree produced by {@link SerpentParser#tx_gas}.
|
* Enter a parse tree produced by {@link SerpentParser#tx_gas}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@ -184,17 +195,6 @@ public interface SerpentListener extends ParseTreeListener {
|
||||||
*/
|
*/
|
||||||
void exitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx);
|
void exitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* Enter a parse tree produced by {@link SerpentParser#msg_func}.
|
|
||||||
* @param ctx the parse tree
|
|
||||||
*/
|
|
||||||
void enterMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
|
||||||
/**
|
|
||||||
* Exit a parse tree produced by {@link SerpentParser#msg_func}.
|
|
||||||
* @param ctx the parse tree
|
|
||||||
*/
|
|
||||||
void exitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enter a parse tree produced by {@link SerpentParser#rel_exp}.
|
* Enter a parse tree produced by {@link SerpentParser#rel_exp}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@ -206,6 +206,17 @@ public interface SerpentListener extends ParseTreeListener {
|
||||||
*/
|
*/
|
||||||
void exitRel_exp(@NotNull SerpentParser.Rel_expContext ctx);
|
void exitRel_exp(@NotNull SerpentParser.Rel_expContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter a parse tree produced by {@link SerpentParser#msg_func}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void enterMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
||||||
|
/**
|
||||||
|
* Exit a parse tree produced by {@link SerpentParser#msg_func}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void exitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enter a parse tree produced by {@link SerpentParser#parse}.
|
* Enter a parse tree produced by {@link SerpentParser#parse}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -421,17 +421,18 @@ public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
|
||||||
@Override
|
@Override
|
||||||
public String visitAsm(@NotNull SerpentParser.AsmContext ctx) {
|
public String visitAsm(@NotNull SerpentParser.AsmContext ctx) {
|
||||||
|
|
||||||
int size = ((SerpentParser.AsmContext) ctx).getChildCount();
|
int size = ctx.asm_symbol().getChildCount();
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
for (int i = 0; i < size ; ++i){
|
for (int i = 0; i < size ; ++i){
|
||||||
|
|
||||||
String symbol = ((SerpentParser.AsmContext) ctx).getChild(i).toString();
|
String symbol = ctx.asm_symbol().children.get(i).toString();
|
||||||
symbol = symbol.trim();
|
symbol = symbol.trim();
|
||||||
|
|
||||||
|
// exclude all that is not an assembly code
|
||||||
if (symbol.equals("[asm") || symbol.equals("asm]") || symbol.equals("\n")) continue;
|
if (symbol.equals("[asm") || symbol.equals("asm]") || symbol.equals("\n")) continue;
|
||||||
|
|
||||||
boolean match = Pattern.matches("[0-9a-fA-F]+", symbol);
|
boolean match = Pattern.matches("[0-9]+", symbol);
|
||||||
if (match){
|
if (match){
|
||||||
|
|
||||||
int byteVal = Integer.parseInt(symbol);
|
int byteVal = Integer.parseInt(symbol);
|
||||||
|
|
|
@ -53,6 +53,13 @@ public interface SerpentVisitor<T> extends ParseTreeVisitor<T> {
|
||||||
*/
|
*/
|
||||||
T visitBlock(@NotNull SerpentParser.BlockContext ctx);
|
T visitBlock(@NotNull SerpentParser.BlockContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a parse tree produced by {@link SerpentParser#asm_symbol}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
* @return the visitor result
|
||||||
|
*/
|
||||||
|
T visitAsm_symbol(@NotNull SerpentParser.Asm_symbolContext ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a parse tree produced by {@link SerpentParser#tx_gas}.
|
* Visit a parse tree produced by {@link SerpentParser#tx_gas}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@ -123,13 +130,6 @@ public interface SerpentVisitor<T> extends ParseTreeVisitor<T> {
|
||||||
*/
|
*/
|
||||||
T visitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx);
|
T visitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* Visit a parse tree produced by {@link SerpentParser#msg_func}.
|
|
||||||
* @param ctx the parse tree
|
|
||||||
* @return the visitor result
|
|
||||||
*/
|
|
||||||
T visitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a parse tree produced by {@link SerpentParser#rel_exp}.
|
* Visit a parse tree produced by {@link SerpentParser#rel_exp}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@ -137,6 +137,13 @@ public interface SerpentVisitor<T> extends ParseTreeVisitor<T> {
|
||||||
*/
|
*/
|
||||||
T visitRel_exp(@NotNull SerpentParser.Rel_expContext ctx);
|
T visitRel_exp(@NotNull SerpentParser.Rel_expContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a parse tree produced by {@link SerpentParser#msg_func}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
* @return the visitor result
|
||||||
|
*/
|
||||||
|
T visitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a parse tree produced by {@link SerpentParser#parse}.
|
* Visit a parse tree produced by {@link SerpentParser#parse}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
|
Loading…
Reference in New Issue