Skip to content

Instantly share code, notes, and snippets.

@wanabe
Created January 17, 2023 10:42
Show Gist options
  • Save wanabe/98680b3aec46a15951efa63eea5b4e97 to your computer and use it in GitHub Desktop.
Save wanabe/98680b3aec46a15951efa63eea5b4e97 to your computer and use it in GitHub Desktop.
# This code is hereby placed in the public domain.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%prefix "calc"
statement <- _ e:expression _ EOL { puts "answer=#{e}" }
/ ( !EOL . )* EOL { warn "error\n" }
expression <- e:term { $$ = e; }
term <- l:term _ PLUS _ r:term { $$ = l + r }
/ l:term _ MINUS _ r:factor { $$ = l - r }
/ e:factor { $$ = e }
factor <- l:factor _ MUL _ r:unary { $$ = l * r }
/ l:factor _ DIV _ r:unary { $$ = l / r }
/ e:unary { $$ = e }
unary <- PLUS _ e:unary { $$ = +e }
/ MINUS _ e:unary { $$ = -e }
/ e:primary { $$ = e }
primary <- primary:PRIMARY { $$ = primary }
/ LPAREN _ e:expression _ RPAREN { $$ = e }
_ <- SPACES?
# token is described by the subset of PEG.
# ex. "123 + 456" will be tokenized "\x01\x09\x03\x09\x01" and {0 => 123, 4 => 456}
# | pos: 0 | pos: 4
# +-> value: 123 +-> value: 456
PRIMARY <-- < [0-9]+ > { $$ = $1.to_i }
EOL <-- '\n' / '\r\n' / '\r' / ';'
PLUS <-- '+'
MINUS <-- '-'
MUL <-- '*'
DIV <-- '/'
LPAREN <-- '('
RPAREN <-- ')'
SPACES <-- [ \t]*
# define parser rules implicitly:
# PRIMARY <- '\x01'
# EOL <- '\x02'
# PLUS <- '\x03'
# MINUS <- '\x04'
# MUL <- '\x05'
# DIV <- '\x06'
# LPAREN <- '\x07'
# RPAREN <- '\x08'
# SPACES <- '\x09'
%%
if ARGV[0]
require "stringio"
str = ARGV[0]
$stdin = StringIO.new("#{str}\n", "r")
end
Calc.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment