龙空技术网

Java实现C编译器:FOR循环语句的解析和执行

余生做酒长醉不忧 160

前言:

眼前咱们对“c语言循环语句无限”都比较看重,小伙伴们都想要学习一些“c语言循环语句无限”的相关资讯。那么小编在网上搜集了一些对于“c语言循环语句无限””的相关资讯,希望朋友们能喜欢,小伙伴们快快来了解一下吧!

本节我们要为解释器增加的功能是for循环,for循环的语法表达式如下:

statement->FOR LP opt_expr test SEMI end_opt_expr RP statement

其对应的执行树结构如下:

对于一个具体的循环语句:

for (i= 0; i < 3; i++) {    a = a + 1;}

i = 0 对应于节点OptExpr, i < 3 对应节点Test, i++ 对应节点EndOptExpr, a = a+ 1; 对应最后一个Statement节点。

解释器在执行for 语句时,先执行OptExpr节点,然后执行Test节点,如果Test节点执行后返回的值大于0,则执行最下面的Statement节点,然后再执行EndOptExpr节点,也就是for 循环后面的i++语句。

整个流程执行完毕后,解释着再次执行Test节点,如果执行后返回值不等于0,则继续执行最下面的Statement节点和EndPotExpr节点,如果返回值等于0,则执行结束。

我们看看相关代码,在CodeTreeBuilder.java中,做以下改动:

public ICodeNode buildCodeTree(int production, String text) {        ICodeNode node = null;        Symbol symbol = null;        switch (production) {        ...         case CGrammarInitializer.FOR_OptExpr_Test_EndOptExpr_Statement_TO_Statement:            node = ICodeFactory.createICodeNode(CTokenType.STATEMENT);            node.addChild(codeNodeStack.pop());            node.addChild(codeNodeStack.pop());            node.addChild(codeNodeStack.pop());            node.addChild(codeNodeStack.pop());            break;            ....case CGrammarInitializer.Expr_Semi_TO_OptExpr:        case CGrammarInitializer.Semi_TO_OptExpr:            node = ICodeFactory.createICodeNode(CTokenType.OPT_EXPR);            if (production == CGrammarInitializer.Expr_Semi_TO_OptExpr) {                node.addChild(codeNodeStack.pop());            }            break;        case CGrammarInitializer.Expr_TO_EndOpt:            node = ICodeFactory.createICodeNode(CTokenType.END_OPT_EXPR);            node.addChild(codeNodeStack.pop());            break;        ...        }

增加的代码就是用来构造前面所说的关于for循环执行树的几个节点。在StatementExecutor的实现中,我们增加了对for循环的这里写代码片实现:

public class StatementExecutor extends BaseExecutor{    private enum LoopType {        FOR,        WHILE,        DO_WHILE    };     @Override      public Object Execute(ICodeNode root) {         int production = (int)root.getAttribute(ICodeKey.PRODUCTION);         switch (production) {         case CGrammarInitializer.FOR_OptExpr_Test_EndOptExpr_Statement_TO_Statement:             //execute OptExpr             executeChild(root, 0);             while( isLoopContinute(root, LoopType.FOR) ) {                 //execute statment in for body                 executeChild(root, 3);                 //execute EndOptExpr                 executeChild(root, 2);              }             break;         default:             executeChildren(root);             break;         }         return root;     }     private boolean isLoopContinute(ICodeNode root, LoopType type) {         ICodeNode res = null;         if (type == LoopType.FOR) {             res = executeChild(root, 1);             int result = (Integer)res.getAttribute(ICodeKey.VALUE);             return result != 0;         }         return false;     }}

xecuteChild(root, 0); 对应于执行树中的OptExpr节点,也就是执行for语句中的变量初始化语句,也就是i = 0; isLoopContinute 执行的是执行树中第二个节点,也就是Test节点,对应的是for 语句中的 i < 3语句,如果返回的结果不等于0,也就是循环条件满足,那么执行循环体内部的语句代码,也就是通过调用

executeChild(root, 3);, 从而执行执最下面的Statement节点,对应于例子中,就是 a = a + 1; 最后通过调用executeChild(root, 2); 执行EndOptExpr节点,对应于for循环,就是语句i++;

我们需要添加新的代码,以便解释器能正确执行i++语句,该语句对应的语法表达式是:

UNARY -> UNARY INCOP

所以我们需要在UnaryNodeExecutor中,添加相应的实现代码,具体改动如下:

public class UnaryNodeExecutor extends BaseExecutor{    @Override    public Object Execute(ICodeNode root) {        executeChildren(root);        ....        switch (production) {        ....         case CGrammarInitializer.Unary_Incop_TO_Unary:            symbol = (Symbol)root.getChildren().get(0).getAttribute(ICodeKey.SYMBOL);            Integer val = (Integer)symbol.getValue();            IValueSetter setter;            setter = (IValueSetter)symbol;            try {                setter.setValue(val + 1);            } catch (Exception e) {                // TODO Auto-generated catch block                e.printStackTrace();                System.err.println("Runtime Error: Assign Value Error");            }            break;        }        }    }

我们先拿到变量i所对应的Symbol对象,通过该对象的ValueSetter接口,使得变量的值自加1.

通过上面的代码改进,我们的解释器对C语言的执行能力可以得到进一步加强,可以正确解析和执行下面的C语言代码:

void f() {int i;int a;i = 0;a = 0;for (i = 0; i < 3; i++) {    a = a + 1;}}

标签: #c语言循环语句无限