首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DFA预测和范围

DFA预测和范围
EN

Stack Overflow用户
提问于 2013-03-14 21:41:37
回答 1查看 261关注 0票数 4

从这个语法开始:https://stackoverflow.com/a/14287002/1082002,我会实现一个简单的语法,它接受和评估简单的语言,如下所示:

代码语言:javascript
复制
{ 
   if a==c { 
      a
      if a==b { 
         b 
      } else { 
         c 
      }
   }

}

因此,如果为a==c,则执行a并计算if a==b,如果为真,则执行b,否则为c。非常简单。

解析器语法和树语法如下:

TreeEvaluator.g (组合语法以生成AST)

代码语言:javascript
复制
grammar TreeEvaluator;

options { 
    output = AST;
}

tokens { 
    CONDBLOCK;
    CODEBLOCK;
    DEFAULT;
}


compilationUnit : block EOF -> block;

condition       : cif elif* celse? -> ^(IF cif elif* celse?);
cif             : IF expr block -> ^(CONDBLOCK expr block);
elif            : ELIF expr block -> ^(CONDBLOCK expr block);
celse           : ELSE block -> ^(DEFAULT block); 
expr            : ID EQ^ ID;
block           : LCUR instruction* RCUR -> ^(CODEBLOCK instruction*);
instruction     : ID | condition;

IF  : 'if';
ELIF: 'elif';
ELSE: 'else';
LCUR: '{';
RCUR: '}';
EQ  : '==';
ID  : ('a'..'z'|'A'..'Z')+;
WS  : (' '|'\t'|'\f'|'\r'|'\n')+ {skip();};

AstTreeEvaluatorParser.g (树解析器)

代码语言:javascript
复制
tree grammar AstTreeEvaluatorParser;

options { 
    output = AST;
    tokenVocab = TreeEvaluator;
    ASTLabelType = CommonTree;
}

@members { 
    private static final class Evaluation {
        boolean matched = false; 
        boolean done = false;
    }

    private java.util.HashMap<String, Integer> vars = new java.util.HashMap<String, Integer>();

    public void addVar(String name, int value){
        vars.put(name, value);
    }

}

compilationUnit : block+;

block        : ^(CODEBLOCK instruction*);

instruction  : ifStat | ID;

ifStat       
@init { Evaluation eval = new Evaluation(); }
         : ^(IF condition[eval]* defcond[eval]?) 
         ;

condition [Evaluation eval]
         : ^(CONDBLOCK exp {if ($exp.value) eval.matched = true;} evalblock[eval])
         ;

defcond [Evaluation eval] 
         : ^(DEFAULT {eval.matched = true;} evalblock[eval]) //force a match
         ;

evalblock [Evaluation eval]     
         : {eval.matched && !eval.done}? //Only do this when a condition is matched but not finished 
        block                //call the execution code
        {eval.done = true;}  //evaluation is complete.
         | ^(CODEBLOCK .*)  //read the code node and continue without executing
         ;

exp returns [boolean value]
        : ^(EQ lhs=ID rhs=ID)
        {$value = vars.get($lhs.getText()) == vars.get($rhs.getText());}
        ;

问题是生成的用于预测规则evalblockSpecialStateTransition(),这个DFA有一个引用参数eval (在规则中指定)的方法,但是在生成的Java类中,该参数是不可见的。

我不明白为什么,是否有办法避免这个问题。

EN

回答 1

Stack Overflow用户

发布于 2013-03-15 00:05:36

您有一个语义谓词(语法{...}?),其中包含对由操作(语法{...})更改的值的引用。在本例中,值是字段Evaluation.matchedEvaluation.done

您应该完全避免这种情况-永远不要包含依赖于操作执行的谓词。相反,可以通过将操作代码包装在if (eval.matched && !eval.done) { ... }中来检查操作中的这些值

²有些人编写的语法以这种方式交互,但我严格避免了它,因为可能会出现像您所看到的那样的问题,以及其他更糟糕的问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15410973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档