Reputation: 1135
I've been puzzling over this for days and searching doesn't seem to give any results. Makes me wonder if it's possible. For example:
funct functionNAME (Object o) { o+1 };
The point is that The user has to use the identifier 'o' within the curly braces and not some other identifier. This is of course specified by the input in the (Object o) part where 'o' can be anything. Basically the identifier within the curly braces must be the same as the identifier defined in the parameter. I know I can store the matched token and print it out to screen but is it possible to use it as a lexical token itself? Thanks.
Upvotes: 0
Views: 2620
Reputation: 16231
Yes there is a better way to do this. You need a symbol table. The job of a symbol table is to keep track of which identifiers can be used at each point in the program. Generally the symbol table also contains other information about the identifiers, such as what they represent (e.g. variable or function name) and what their types are.
Using a symbol table you can detect the use of variables that are not in scope during parsing for many languages but not all. E.g. C and Pascal are languages where identifiers must be declared before they are used (with a few exceptions). But other languages (e.g. Java) allow identifiers to be declared after they are used and in that case it is best not to try to detect errors such as use of an undeclared variable until after the program is parsed. (Indeed in Java you need to wait until all files are parsed, as identifiers might be declared in another file.)
I'll assume a simple scenario, which is that you only need to record information about variables, that there is no type information, and that things must be declared before use. That will get you started. I haven't bothered about adding the function name to the symbol table.
Suppose a symbol table is a stack of things called frames. Each frame is a mutable set of strings. (Later you may want to change that to a mutable map from strings to some additional information.)
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>
}
Upvotes: 2
Reputation: 1135
Okay I have worked out a way to get what I want based on the example I gave in OP. It is a simple variant of the solution I have implemented in mine just to give a proof of concept. Trivial things such as token definitions will be left out for simplicity.
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>
}
Is there a better way to do this?
Upvotes: 0
Reputation: 19776
you can store the value of the identifier matchin o
, and then check in the curly brace if the identifier there is the same, and, if not, throw an Exception.
Upvotes: 0