如何在新创建的Context的子级中设置字符串

时间:2019-01-31 19:04:30

标签: string antlr4 children

我有一个解析器,该解析器使用XContext调用visitX方法,该XContext包含解析为ArrayNode和FunctionName的表达式。我可以检索该函数的对象,并希望为此数组中的每个元素调用此函数的调用,但是该函数需要一个ExpressionVisitor和一个YContext。我可以创建一个新的YContext(XContext),并且子级为空。我需要将我的array.get(i)作为TerminalNode添加到children数组中,以便接收YContext的函数可以检查child的数量(1),然后获取值(例如ctx.exprValues()。exprList() .expr(0))。

TerminalNodeImpl可以使用Token(这是一个接口),但我还没有找到使用可以采用JsonNode值(例如String,int,Object)的实现类来创建Token的方法。

YContext子级是一个List,但是我不确定是什么实现了可以使用JsonNode值构造的ParseTree。

我尝试使用这样的代码解析JsonNode值,但是我无法在令牌中得到任何可以在我的新上下文中使用addAnyChild的东西...

            for (int i=0;i<mapArray.size();i++) {
            ANTLRInputStream input = new ANTLRInputStream(mapArray.get(i).asText());

            MappingExpressionLexer lexer = new MappingExpressionLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lexer);

我确信我忽略了一些简单的事情。在其他情况下,我已经可以将值压入堆栈,但是在这种情况下,我可以调用的所有函数都使用YContext,因此我需要以某种方式将值放入YContext.children。

1 个答案:

答案 0 :(得分:0)

该解决方案很复杂,但根据表达式的定义方式是必需的。我跟踪了传递给该函数的ctx,以便了解其结构:

Function_callContext:
---------------------
TerminalNodeImpl  $string        44 '$string'
ExprValuesContext
   TerminalNodeImpl  (           2  '('
   ExpressionListContext
      NumberContext
         TerminalNodeImpl   1    22 '1'
   TerminalNodeImpl  )           3  ')'
TerminalNodeImpl  $string        44 '$string'

Because the parser is looking for:
expr :
...
 | VAR_ID exprValues                          # function_call
...
;
...
exprList : expr (',' expr)* ;
exprValues : '(' exprList ')' ;
VAR_ID : '$' ID ;
ID : [a-zA-Z] [a-zA-Z0-9_]*;

,我找到了CommonTokenFactory,让我创建可以放在TerminalNodeImpl中的令牌,以便建立正确的上下文。

这是代码(我现在只实现了NUMBER,但稍后会添加异常和其他类型...我的测试是使用$ map([1 .. 5],$ string)示例(其中[1..5]是成为数组的序列。

            for (int i = 0; i < mapArray.size(); i++) {
               Function_callContext callCtx = new Function_callContext(ctx);
               // note: callCtx.children should be empty unless carrying an
               // exception
               ExprListContext elc = new ExprListContext(callCtx.getParent(),callCtx.invokingState);
               ExprValuesContext evc = new ExprValuesContext(callCtx.getParent(),callCtx.invokingState);
               evc.addAnyChild(new TerminalNodeImpl(CommonTokenFactory.DEFAULT.create(MappingExpressionParser.T__1,"(")));
               CommonToken token = null;
               JsonNode element = mapArray.get(i);
               switch (element.getNodeType()) {
                  case ARRAY: {
                     break;
                  }
                  case BINARY:
                     break;
                  case BOOLEAN:
                     break;
                  case MISSING:
                     break;
                  case NULL:
                     break;
                  case NUMBER:
                     token = CommonTokenFactory.DEFAULT.create(MappingExpressionParser.NUMBER,element.asText());
                     TerminalNodeImpl tn = new TerminalNodeImpl(token);
                     NumberContext nc = new NumberContext(callCtx);
                     nc.addAnyChild(tn);
                     elc.addAnyChild(nc);
                     evc.addAnyChild(elc);
                     break;
                  case OBJECT:
                     break;
                  case POJO:
                     break;
                  case STRING:
                     break;
                  default:
                     break;
               }
               evc.addAnyChild(new TerminalNodeImpl(CommonTokenFactory.DEFAULT.create(MappingExpressionParser.T__1,")")));
               callCtx.addAnyChild(var);
               callCtx.addAnyChild(evc);
               result = function.invoke(this, callCtx);
               resultArray.add(result);
            }