Let me continue here, the orginal thread "negative floats and unary
minus" is closed
On 17 Set 2002, 11:39, arsf10 <ars...@[EMAIL PROTECTED]
> wrote:
http://groups.google.com/group/comp.compilers.tools.javacc/browse_thread/thread/3bdfad0d0fe95cf6/f652f4c4c9be54f7?lnk=gst&q=unary+minus&rnum=1#f652f4c4c9be54f7
> eric,
>
> from your comments (and sreeni's), i understand that i should be
handling
> the context of the '-' in the parser and not try to magically have
javacc
> interpret the '-' as a token in 3 different ways, which is impossible
Well, does it mean that the recognition should be faced by the parser.
Right?
> i separated the problem into the lexical states of an unambiguous
negative
> integer, a subtraction operation, and aunaryminusoperation in the
> parser section
To lead the lexer (token manager) in a given lexical states would
require a given, specific prefix...
In the parser section (non terminals) ? I'm confused here between the
parser and the lexer roles.
> and i can parse my cases correctly.
Any example/excerpt of the solution for beginners?
I tried to add the unary minus to my Gpl.jj grammar (derived from
NL_Xlator), following two hints:
1) Theo's tutorial, 1.3.6 Adding parentheses, a unary operator, and
history, p. 20-22
http://www.engr.mun.ca/~theo/JavaCC-Tutorial/
2) the Sreeeny's one
You need to parse unary minus as an operator if you want to satisfy
all your constraints
http://groups.google.com/group/comp.compilers.tools.javacc/browse_thread/thread/83ed89955106ac0c/e0d44dcd20b6736c?lnk=gst&q=unary+minus&rnum=2#e0d44dcd20b6736c
Well, the result is that the unary minus (now recognized by the
Factor() non terminal) breaks some unit tests: the unary minus
operator wins, per associativity, on the additive, binary minus
operator.
E.g. the expression
a - b
is tokenized in the "a" and "-b" tokens and then (erroneously) leads
the parser to the following diagnostic
Exception in thread "main" ... ioni.gpl.ParseException: Encountered
"-" at line 1, column 3.
Was expecting one of:
<ADD_ARITHMETIC_OP> ...
<MULT_ARITHMETIC_OP> ...
";" ...
Currently I have not enabled (nor tested) yet the reg expr for numbers
(the next thing to do!) and the expressions currently involve only
identifiers.
The original six-points list (orginal thread) gets, for Gpl
1. -a (and (-a)) parse as the token -a (between parenthesis); works
fine;
2. -a+b parse as addition of the token -a, the operation 'addition'
and b; works fine. a + -b works fine, as well
3. (exponentiation, not sup****ted)
4. (exponentiation, not sup****ted)
5. a-b to parse as the token -a, the operation 'subtraction', and the
token b does NOT works anymore (utest regression)
6. a--b to parse as the token a, the operation 'subtraction', and the
token -b, does NOT works
7. funct(-a), to be implemented, yet
You shall be able (when numbers will be added) to replace identifiers
such as a or b with a well formed numbers (numeric literal constants);
the reg expr has been tem****ary removed for sake of simplicity and I
omit it here.
Instead of alternatively hack as suggested by Eric (see above).
> expression ::= expression <NEGATIVE_INTEGER>
I would prefer to do (and to learn) the right thing
> you may need to use lexical states so that
> finding a negative number is only permitted in certain states
Mumble mumble let me try...
When I've just got a Factor() the "-" token shall be always
recognized as the binary additive minus operator
or, in other terms, the rule to recognize a negated operand (factor)
should be switched off
or in other terms, the rule to recognize a negated operand (factor)
should be switched on only when a factor is expected
But, the problem is that Factor() is a nonterminal (see the grammar
below) i.e. parser's stuff, not lexer's one.
The handling of lexical states, instead, seems to be done
http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm#tth_sEc3.11
at.. lexical level i.e. acting on the token manager and its reg
expresssions.
I'm quite confused
Any clarification&help would be greatly appreciated.
Thanks in advance.
Cesare
Just here below the Gpl.jj grammar
-----------------
options
{
STATIC = true;
UNICODE_INPUT = true;
}
PARSER_BEGIN(Gpl)
package it.finmatica.gpj.ec.istruzioni.gpl;
public class Gpl
{
public static
void
main( String args[] ) throws ParseException
{
Gpl lParser = new Gpl( System.in );
lParser.ExpressionList();
}
} // end class Gpl
PARSER_END(Gpl)
SKIP :
{ " "
| "\t"
| "\n"
| "\r"
}
TOKEN : // Basics
{ <#LETTER : ["a"-"z", "A"-"Z"] >
| <#DIGIT : ["0"-"9"] >
| <PAR_OPEN : ["("] >
| <PAR_CLOSED : [")"] >
}
/***
TOKEN : // Numeric literal costants
{
< NUMBER_LITERAL: <FLOAT> >
| < #FLOAT
: <INTEGER>
| <INTEGER> ( <FRACTIONAL_PART_SEPARATOR> <INTEGER> )?
>
| < #INTEGER: ( <DIGIT> )+ >
| < #FRACTIONAL_PART_SEPARATOR: "," >
}
***/
TOKEN : // Additive and multiplicative arithmetic operators, unary
minus
{ <ADD_ARITHMETIC_OP: ["+", "-"] >
| <MULT_ARITHMETIC_OP: ["*", "/"] >
| <UNARY_MINUS: ["-"] >
}
TOKEN : // (group) identifiers
{ <GROUP_ID : <ID> ( <GROUP_ID_SEPARATOR> <ID> )* >
| <#ID : ( <LETTER> | "_" ) ( <LETTER> | "_" | <DIGIT> )* >
| <GROUP_ID_SEPARATOR : "." >
}
void
ExpressionList() :
{
String lString;
}
{
{
System.out.println( "Type in an expression followed by a \";\" or ^D
to quit:" );
System.out.println( "" );
}
( lString = Expression() ";"
{
System.out.println( lString );
System.out.println("");
System.out.println("Type in another expression followed by a \";\"
or ^D to quit:" );
System.out.println("");
}
)*
<EOF>
} // end Gpl.ExpressionList()
String
Expression() :
{
java.util.Vector<String> lOpImages = new java.util.Vector<String>();
java.util.Vector<String> lTermImages = new
java.util.Vector<String>();
String lResult;
Token lAddArithmeticOp = null;
}
{
lResult = Term()
{
lTermImages.addElement( lResult );
}
( lAddArithmeticOp = <ADD_ARITHMETIC_OP> lResult = Term()
{
lOpImages.addElement( lAddArithmeticOp.image );
lTermImages.addElement( lResult );
}
)*
{
if ( lTermImages.size() == 1 )
{
lResult = lTermImages.elementAt(0);
return lResult;
}
else
{
lResult = lTermImages.elementAt(0);
for ( int i = 1; i < lTermImages.size(); i++ )
{
boolean lIsSum = lOpImages.elementAt( i - 1 ).equals( "+" );
lResult += (lIsSum ? " plus " : " minus ")
+ lTermImages.elementAt( i )
;
}
return lResult;
}
}
} // end Gpl.Expression()
String
Term() :
{
java.util.Vector<String> lOpImages = new java.util.Vector<String>();
java.util.Vector<String> lFactorImages = new
java.util.Vector<String>();
String lResult;
Token lMultArithmeticOp = null;
}
{
lResult = Factor()
{
lFactorImages.addElement( lResult );
}
(
lMultArithmeticOp = <MULT_ARITHMETIC_OP> lResult = Factor()
{
lOpImages.addElement( lMultArithmeticOp.image );
lFactorImages.addElement( lResult );
}
)*
{
if ( lFactorImages.size() == 1 )
{
lResult = lFactorImages.elementAt(0);
return lResult;
}
else
{
lResult = lFactorImages.elementAt(0);
for ( int i = 1; i < lFactorImages.size(); i++ )
{
boolean lIsMult = lOpImages.elementAt( i - 1 ).equals( "*" );
lResult += (lIsMult ? " times " : " divide ")
+ lFactorImages.elementAt( i )
;
}
return lResult;
}
}
} // end Gpl.Term()
String
Factor() :
{
Token lParOpenToken, lParClosedToken;
Token lUnaryMinus;
String lResult;
}
{
lResult = Primary()
{
return lResult;
}
| lParOpenToken = <PAR_OPEN> lResult = Expression() lParClosedToken =
<PAR_CLOSED>
{
lResult = lParOpenToken + " " + lResult + " " + lParClosedToken;
return lResult;
}
| lUnaryMinus = <UNARY_MINUS> lResult = Factor()
{
lResult = lUnaryMinus + lResult;
return lResult;
}
} // end Gpl.Factor()
// Narrows the accepted input to group identifiers which do NOT
contain any GROUP_ID_SEPARATOR
// see also comp.compilers.tools.javacc, Unit tests for JavaCC tokens
and productions
String
Id() :
{
Token lToken;
String lResult;
disable_tracing();
}
{
lToken = <GROUP_ID>
{
lResult = lToken.image;
String lQuotedGroupIdSeparator =
GplConstants.tokenImage[GROUP_ID_SEPARATOR];
int lIndexOfHeadingingQuotes =
lQuotedGroupIdSeparator.indexOf( '"' );
int lIndexOfTrailingQuotes =
lQuotedGroupIdSeparator.lastIndexOf( '"' );
String lGroupIdSeparator =
lQuotedGroupIdSeparator.substring( lIndexOfHeadingingQuotes + 1,
lIndexOfTrailingQuotes );
if ( lResult.indexOf( lGroupIdSeparator ) != -1 )
{
throw new ParseException( "\"" + lGroupIdSeparator +
"\" (<GROUP_ID_SEPARATOR>) in identifier: " + lResult );
}
return lResult;
}
} // end Gpl.Id()
String
GroupId() :
{
Token lToken;
String lResult;
}
{
lToken = <GROUP_ID>
{
lResult = lToken.image;
return lResult;
}
} // end Gpl.GroupId()
String
Primary() :
{
Token lToken;
String lResult;
}
{
lToken = <GROUP_ID>
{
lResult = lToken.image;
return lResult;
}
} // end Gpl.Primary()
// EOF, in unit testing allows to test a given input and not a prefix
// (see also:
http://groups.google.com/group/comp.compilers.tools.javacc/browse_thread/thread/e33401b7c7c81b66/cede39f37111bc73#cede39f37111bc73)
String
Eof() :
{
Token lToken;
String lResult;
}
{
lToken = <EOF>
{
lResult = lToken.image;
return lResult;
}
// <NUMBER_LITERAL> here soon
} // end Gpl.Eof()


|