本文介绍了循环,开关,嵌入式返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是来自简单解析器的代码片段。


返回被隐藏在switch语句中(实际的

开关还有几个案例)。我不能想出一个好的

替代方案我更喜欢。有任何想法吗?我已经尝试了''

(!完)''的方法,但是跟踪标志似乎没有任何比嵌入式的更好的价值。 'return''。


符号get_sym(void);

符号符号;


void stmt_seq(void ){;;}
for(;;){

switch(sym){

case ident_sym:ident_stmt(); break;

case while_sym:while_stmt(); break;

case if_sym:if_stmt();休息;


case endwhile_sym:

case else_sym:

case endif_sym:

case eof_sym:

返回;


默认值:

错误(期待stmt);

get_sym ();

}

}

}

解决方案




像往常一样,我先看了一下代码,然后用它来弄清楚什么是错的

,只有当我找不到任何东西时,我才会读到这个问题。

我的答案是,这是完全可读的,具有明显的语义。

用不必要的标志来混淆它只会混淆它。但是,正如他们所说的那样,美女是啤酒持有人眼中的一面,所以我相信你会得到数百个反对的回复。一如既往的风格问题。


彼得





我的版本,坚持每个解析器返回它的终止

符号(一个符号前瞻):


符号get_sym(void);


符号stmt_seq(符号符号)

{

while(eof_sym!= sym){

switch(sym) {

case ident_sym:

sym = ident_stmt(sym); break;

case while_sym:

sym = while_stmt(sym); break;

case if_sym:

sym = if_stmt(sym);休息;


case endwhile_sym:

case else_sym:

case endif_sym:

case eof_sym:

休息;


默认:

错误(期待stmt);

sym = get_sym();

} / * switch * /

if(sym == eof_sym)break;

} / * while * /

返回sym;

} / * stmt_seq * /


有关错误处理的一般查询,google搜索源,非常清楚。 Pascal具有set原语,

,您可以在C中或多或少地模拟。现在每个构造都是由可能的初始符号I和一组来限定的。

可能的终止符号T.您可以通过扫描过去的错误时不能忽略的那些

符号来扩充集合T.然后

的基本想法是这样的:


做{

而(sym IN I){

parse(sym); sym = nextsym();

}

} while(!(sym in T));


今天大多数编译器使用解析器生成器,例如YACC或BISON,

而不是简单的递归下降。递归下降

通常有更好的错误处理。


可能的符号的枚举将有所帮助。如果enum是

被安排来用单个位来描述它们,那么设置的实现是琐碎的。


enum syms {EOsrc, WHILE,FOR,IF = 4,ELSE = 8,DO = 16 ....};


如果没有
超过31个。有些可以组合在一起,例如MULOP

(*,/),ADDOP(+。 - ),RELOP(<,>,< =,> =,== ,! =)。这是语言设计的一部分




-

查克F(cb ******** @ yahoo.com)(cb********@worldnet.att.net)

可用于咨询/临时嵌入式和系统。

< http: //cbfalconer.home.att.net>使用worldnet地址!




它是通常很好的做法,用一个独特的退出来写函数

点。但是对于像这个一样短的功能,它实际上并不是很重要。阅读它的程序员可能会同时在屏幕上看到退出

点,所以

理解并不困难。

The following is a code fragment from a simple parser.

The return is buried inside the switch statement (the actual
switch has several more cases). I can''t come up with a good
alternative I like better. Any ideas? I''ve tried the ''while
(!done)'' approach, but keeping track of the flag doesn''t seem any
better than the embedded ''return''.

Symbol get_sym(void);
Symbol sym;

void stmt_seq(void) {
for (;;) {
switch (sym) {
case ident_sym : ident_stmt(); break;
case while_sym : while_stmt(); break;
case if_sym: if_stmt(); break;

case endwhile_sym:
case else_sym:
case endif_sym:
case eof_sym:
return;

default:
error("expecting stmt");
get_sym();
}
}
}

解决方案



As usual, I looked at the code first and tried to figure out what''s wrong
with it, and only when I still could not find anything, I read the question.
My answer would be that this is perfectly readable with obvious semantics.
Cluttering it with unnecessary flags would only obfuscate it. But, as they
say, beauty is in the eyes of beer holder, so I am sure you will get
hundreds of opposing replies. As always with style issues.

Peter




My version, insisting that each parser return its termination
symbol (one symbol lookahead):

Symbol get_sym(void);

Symbol stmt_seq(Symbol sym)
{
while (eof_sym != sym) {
switch (sym) {
case ident_sym :
sym = ident_stmt(sym); break;
case while_sym :
sym = while_stmt(sym); break;
case if_sym:
sym = if_stmt(sym); break;

case endwhile_sym:
case else_sym:
case endif_sym:
case eof_sym:
break;

default:
error("expecting stmt");
sym = get_sym();
} /* switch */
if (sym == eof_sym) break;
} /* while */
return sym;
} /* stmt_seq */

For your general query about error handling, google for the source
to PascalS, which is very clear. Pascal has the set primitive,
which you can simulate more or less in C. Now each construct is
qualified by the set of possible initial symbols I, and the set of
possible termination symbols T. You augment the set T by those
symbols that must not be ignored in scanning past an error. Then
the basic idea is something like:

do {
while (sym IN I) {
parse(sym); sym = nextsym();
}
} while (!(sym in T));

Most compilers today use parser generators, such as YACC or BISON,
rather than the simpler recursive descent. Recursive descent
usually has better error handling.

An enum of the possible syms will be helpful. If the enum is
arranged to describe them by single bits the set implementation is
trivial.

enum syms {EOsrc, WHILE, FOR, IF = 4, ELSE = 8, DO = 16 ....};

and you can keep the sets in a single unsigned long if you have no
more than 31 of them. Some can be grouped together, such as MULOP
(*, /), ADDOP (+. -), RELOP (<, >, <=, >=, ==, !=). This is part
of language design.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!



It is normally good practice to write functions with one unique exit
point. But for a function as short as this one it doesn''t really
matter so much. The programmer reading it can probably see both exit
points on their screen at the same time, so it''s not difficult to
understand.


这篇关于循环,开关,嵌入式返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 19:52