Skip to content

Commit

Permalink
d: change YYLocation's type from class to struct
Browse files Browse the repository at this point in the history
This avoids heap allocation and gives minimal costs for the
creation and destruction of the YYParser.Symbol struct if
the location tracking is active.

Suggested by H. S. Teoh.

* data/skeletons/lalr1.d: Here.
* doc/bison.texi: Document it.
* examples/d/calc/calc.y: Adjust.
* tests/calc.at: Test it.
  • Loading branch information
adelavais authored and akimd committed Nov 20, 2020
1 parent 10305f3 commit e5854bb
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 38 deletions.
20 changes: 8 additions & 12 deletions data/skeletons/lalr1.d
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ static assert(__traits(compiles, (new string[1])[0]=(new ]b4_location_type[[1])[
private immutable bool yy_location_is_class = !__traits(compiles, *(new ]b4_location_type[((new ]b4_position_type[[1])[0])));]], [[
/**
* A class defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> class, denote a point in the input.
* A struct defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> struct, denote a point in the input.
* Locations represent a part of the input through the beginning
* and ending positions. */
public class ]b4_location_type[
public struct ]b4_location_type[
{
/** The first, inclusive, position in the range. */
public ]b4_position_type[ begin;
Expand All @@ -159,9 +159,6 @@ public class ]b4_location_type[
this.begin = this.end = loc;
}
public this () {
}
/**
* Create a <code>]b4_location_type[</code> from the endpoints of the range.
* @@param begin The first position included in the range.
Expand All @@ -173,10 +170,9 @@ public class ]b4_location_type[
}
/**
* A representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>toString</code>
* method. */
public override string toString () const {
* A representation of the location.
*/
public string toString () const {
auto end_col = 0 < end.column ? end.column - 1 : 0;
auto res = begin.toString ();
if (end.filename && begin.filename != end.filename)
Expand All @@ -189,7 +185,7 @@ public class ]b4_location_type[
}
}
private immutable bool yy_location_is_class = true;
private immutable bool yy_location_is_class = false;
]])])m4_ifdef([b4_user_union_members], [private union YYSemanticType
{
Expand Down Expand Up @@ -438,7 +434,7 @@ b4_symbol_type_define
/* Error handling. */
int yynerrs_ = 0;]b4_locations_if([[
/// The location where the error started.
]b4_location_type[ yyerrloc = null;
]b4_location_type[ yyerrloc;
/// ]b4_location_type[ of the lookahead.
]b4_location_type[ yylloc;
Expand Down
4 changes: 2 additions & 2 deletions doc/bison.texi
Original file line number Diff line number Diff line change
Expand Up @@ -13844,8 +13844,8 @@ can be used to print the semantic values. This however may change
@c - class Location

When the directive @code{%locations} is used, the D parser supports
location tracking, see @ref{Tracking Locations}. The position
structure and the location class are provided.
location tracking, see @ref{Tracking Locations}. The position and
the location structures are provided.

@deftypeivar {YYLocation} {YYPosition} begin
@deftypeivarx {YYLocation} {YYPosition} end
Expand Down
18 changes: 9 additions & 9 deletions examples/d/calc/calc.y
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ if (isInputRange!R && is(ElementType!R : dchar))
}

if (input.empty)
return Calc.Symbol(TokenKind.YYEOF, new YYLocation(startPos, endPos));
return Calc.Symbol(TokenKind.YYEOF, YYLocation(startPos, endPos));

// Numbers.
if (input.front.isNumber)
Expand All @@ -143,7 +143,7 @@ if (isInputRange!R && is(ElementType!R : dchar))
}
start = end;
end.column += lenChars;
return Calc.Symbol(TokenKind.NUM, semanticVal_.ival, new YYLocation(startPos, endPos));
return Calc.Symbol(TokenKind.NUM, semanticVal_.ival, YYLocation(startPos, endPos));
}

// Individual characters
Expand All @@ -153,17 +153,17 @@ if (isInputRange!R && is(ElementType!R : dchar))
end.column++;
switch (ch)
{
case '+': return Calc.Symbol(TokenKind.PLUS, new YYLocation(startPos, endPos));
case '-': return Calc.Symbol(TokenKind.MINUS, new YYLocation(startPos, endPos));
case '*': return Calc.Symbol(TokenKind.STAR, new YYLocation(startPos, endPos));
case '/': return Calc.Symbol(TokenKind.SLASH, new YYLocation(startPos, endPos));
case '(': return Calc.Symbol(TokenKind.LPAR, new YYLocation(startPos, endPos));
case ')': return Calc.Symbol(TokenKind.RPAR, new YYLocation(startPos, endPos));
case '+': return Calc.Symbol(TokenKind.PLUS, YYLocation(startPos, endPos));
case '-': return Calc.Symbol(TokenKind.MINUS, YYLocation(startPos, endPos));
case '*': return Calc.Symbol(TokenKind.STAR, YYLocation(startPos, endPos));
case '/': return Calc.Symbol(TokenKind.SLASH, YYLocation(startPos, endPos));
case '(': return Calc.Symbol(TokenKind.LPAR, YYLocation(startPos, endPos));
case ')': return Calc.Symbol(TokenKind.RPAR, YYLocation(startPos, endPos));
case '\n':
{
end.line++;
end.column = 1;
return Calc.Symbol(TokenKind.EOL, new YYLocation(startPos, endPos));
return Calc.Symbol(TokenKind.EOL, YYLocation(startPos, endPos));
}
default: assert(0);
}
Expand Down
30 changes: 15 additions & 15 deletions tests/calc.at
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ class CalcLexer(R) : Lexer
]AT_YYERROR_DEFINE[

YYSemanticType semanticVal_;]AT_LOCATION_IF([[
YYLocation location = new YYLocation;
YYLocation location;

public final @property YYPosition startPos()
{
Expand Down Expand Up @@ -606,13 +606,13 @@ class CalcLexer(R) : Lexer

// EOF.
if (input.empty)
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EOF]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EOF]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);

// Numbers.
if (input.front.isNumber)
{
semanticVal_.ival = parseInt;
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[NUM, semanticVal_.ival]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[NUM, semanticVal_.ival]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
}

// Individual characters
Expand All @@ -630,22 +630,22 @@ class CalcLexer(R) : Lexer
if (c == '#')
{
stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[YYerror]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[YYerror]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
}

switch (c)
{
case '+': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[PLUS]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '-': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[MINUS]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '*': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[STAR]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '/': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[SLASH]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '(': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[LPAR]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case ')': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[RPAR]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '\n': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EOL]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '=': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EQUAL]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '^': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[POW]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '!': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[NOT]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
default: return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[YYUNDEF]AT_LOCATION_IF([[, new YYLocation(startPos, endPos)]])[);
case '+': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[PLUS]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '-': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[MINUS]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '*': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[STAR]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '/': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[SLASH]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '(': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[LPAR]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case ')': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[RPAR]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '\n': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EOL]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '=': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[EQUAL]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '^': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[POW]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
case '!': return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[NOT]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
default: return YYParser.Symbol(TokenKind.]AT_TOKEN_PREFIX[YYUNDEF]AT_LOCATION_IF([[, YYLocation(startPos, endPos)]])[);
}
}
}
Expand Down

0 comments on commit e5854bb

Please sign in to comment.