这几天我一直对此感到困惑,搜索似乎没有给出任何结果。让我想知道这是否可能。例如:
funct functionNAME (Object o) { o+1 };
关键是用户必须在花括号内使用标识符“o”,而不是其他标识符。这当然是由 (Object o) 部分中的输入指定的,其中 'o' 可以是任何东西。基本上花括号内的标识符必须与参数中定义的标识符相同。我知道我可以存储匹配的标记并将其打印到屏幕上,但是否可以将其用作词法标记本身?谢谢。
是的,有更好的方法来做到这一点。你需要一个符号表。符号表的工作是跟踪程序中每个点可以使用哪些标识符。通常,符号表还包含有关标识符的其他信息,例如它们表示的内容(例如变量或函数名称)以及它们的类型。
使用符号表,您可以检测在解析许多语言(但不是全部)期间不在范围内的变量的使用。例如,C 和 Pascal 是必须在使用标识符之前声明标识符的语言(有一些例外)。但是其他语言(例如Java)允许在使用标识符之后声明标识符,在这种情况下,最好不要尝试检测错误,例如在程序被解析之前使用未声明的变量。(实际上,在 Java 中,您需要等到所有文件都被解析,因为标识符可能会在另一个文件中声明。)
我假设一个简单的场景,就是你只需要记录变量的信息,没有类型信息,使用前必须声明。这会让你开始。我没有为将函数名添加到符号表而烦恼。
假设一个符号表是一堆叫做帧的东西。每个帧都是一组可变的字符串。(稍后您可能希望将其更改为从字符串到一些附加信息的可变映射。)
void Start(): { }
{
<FUNCTION>
<IDENTIFIER>
{symttab.pushNewFrame() ;}
<LBRACKET> Parameters() <RBRACKET>
<LBRACE> Expression() <RBRACE>
{symtab.popFrame() ; }
}
void Parameters() : {}
{
( Parameter() (<COMMA> Parameter() )* )?
}
void Parameter() : { Token x ; }
<OBJECT> x=<IDENTIFIER>
{ if( symtab.topFrame().contains(x.image) ) reportError( ... ) ; }
{ symtab.topFrame().add(x.image) ; }
}
void Expression() : { }
{
Exp1() ( <PLUS> Exp1() )*
}
void Exp1() : { Token y ; }
{
y = <IDENTIFIER>
{ if( ! symtab.topFrame().contains(y.image) ) reportError( ... ) ; }
|
<NUMBER>
}
您可以存储标识符 matchin 的值o
,然后在大括号中检查标识符是否相同,否则抛出异常。
好的,我已经根据我在 OP 中给出的示例找到了一种方法来获得我想要的东西。这是我在我的解决方案中实现的一个简单变体,只是为了提供概念证明。为简单起见,将省略诸如令牌定义之类的琐碎事情。
void Start():
{
Token x, y;
}
{
<FUNCTION>
<FUNCTION_NAME>
<LBRACKET>
<OBJECT>
x = <PARAMETER>
<RBRACKET>
<LBRACE>
y = <PARAMETER>
{
if (x.image.equals(y.image) == false)
{
System.out.println("Identifier must be specified in the parameters.");
System.exit(0);
}
}
<PLUS>
<DIGIT>
<RBRACE>
<COLON>
}
有一个更好的方法吗?