1 /* Parser and scanner for calc in D. -*- D -*-
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 %define api.parser.class
{Calc
}
23 %define parse.
error verbose
31 /* Bison Declarations */
40 %token
<ival
> NUM
"number"
45 %precedence UNARY
/* unary operators */
56 | exp EOL
{ writeln
($exp); }
62 | exp
"+" exp
{ $$
= $1 + $3; }
63 | exp
"-" exp
{ $$
= $1 - $3; }
64 | exp
"*" exp
{ $$
= $1 * $3; }
65 | exp
"/" exp
{ $$
= $1 / $3; }
66 |
"+" exp %prec UNARY
{ $$
= $2; }
67 |
"-" exp %prec UNARY
{ $$
= -$2; }
68 |
"(" exp
")" { $$
= $2; }
72 import std.range.primitives
;
75 auto calcLexer
(R
)(R range
)
76 if
(isInputRange
!R
&& is
(ElementType
!R
: dchar
))
78 return new CalcLexer
!R
(range
);
81 auto calcLexer
(File f
)
83 import std.algorithm
: map
, joiner
;
84 import std.utf
: byDchar
;
86 return f.byChunk
(1024) // avoid making a syscall roundtrip per char
87 .map
!(chunk
=> cast
(char[]) chunk
) // because byChunk returns ubyte[]
88 .joiner
// combine chunks into a single virtual range of char
89 .calcLexer
; // forward to other overload
92 class CalcLexer
(R
) : Lexer
93 if
(isInputRange
!R
&& is
(ElementType
!R
: dchar
))
97 this
(R r
) { input
= r
; }
102 // Should be a local in main, shared with %parse-param.
105 void yyerror(YYLocation loc
, string s
)
108 stderr.writeln
(loc.toString
(), ": ", s
);
111 YYSemanticType semanticVal_
;
113 public final @property YYSemanticType semanticVal
()
120 import std.uni
: isWhite
, isNumber
;
122 // Skip initial spaces
123 while
(!input.empty
&& input.front
!= '\n' && isWhite
(input.front
))
131 return TokenKind.YYEOF
;
134 if
(input.front.isNumber
)
138 import std.conv
: parse
;
139 semanticVal_.ival
= input.parse
!int;
140 while
(!input.empty
&& copy.front
!= input.front
)
146 end.column
+= lenChars
;
147 return TokenKind.NUM
;
150 // Individual characters
151 auto ch
= input.front
;
157 case
'=': return TokenKind.EQ
;
158 case
'+': return TokenKind.PLUS
;
159 case
'-': return TokenKind.MINUS
;
160 case
'*': return TokenKind.STAR
;
161 case
'/': return TokenKind.SLASH
;
162 case
'(': return TokenKind.LPAR
;
163 case
')': return TokenKind.RPAR
;
168 return TokenKind.EOL
;
174 YYPosition startPos
() const
179 YYPosition endPos
() const
187 auto l
= calcLexer
(stdin
);
188 auto p
= new Calc
(l
);
190 return l.exit_status
;