185 lines
3.7 KiB
Ruby
185 lines
3.7 KiB
Ruby
#--
|
|
# DO NOT MODIFY!!!!
|
|
# This file is automatically generated by rex 1.0.5
|
|
# from lexical definition file "c.rex".
|
|
#++
|
|
|
|
require 'racc/parser'
|
|
class C < Racc::Parser
|
|
require 'strscan'
|
|
|
|
class ScanError < StandardError ; end
|
|
|
|
attr_reader :lineno
|
|
attr_reader :filename
|
|
attr_accessor :state
|
|
|
|
def scan_setup(str)
|
|
@ss = StringScanner.new(str)
|
|
@lineno = 1
|
|
@state = nil
|
|
end
|
|
|
|
def action
|
|
yield
|
|
end
|
|
|
|
def scan_str(str)
|
|
scan_setup(str)
|
|
do_parse
|
|
end
|
|
alias :scan :scan_str
|
|
|
|
def load_file( filename )
|
|
@filename = filename
|
|
open(filename, "r") do |f|
|
|
scan_setup(f.read)
|
|
end
|
|
end
|
|
|
|
def scan_file( filename )
|
|
load_file(filename)
|
|
do_parse
|
|
end
|
|
|
|
|
|
def next_token
|
|
return if @ss.eos?
|
|
|
|
# skips empty actions
|
|
until token = _next_token or @ss.eos?; end
|
|
token
|
|
end
|
|
|
|
def _next_token
|
|
text = @ss.peek(1)
|
|
@lineno += 1 if text == "\n"
|
|
token = case @state
|
|
when nil
|
|
case
|
|
when (text = @ss.scan(/\/\/.+/))
|
|
action {}
|
|
|
|
when (text = @ss.scan(/(\w+:)?[A-Z]+\s.+;/))
|
|
action { [:ASM,text]}
|
|
|
|
when (text = @ss.scan(/(\w+:).*;/))
|
|
action { [:ASM,text]}
|
|
|
|
when (text = @ss.scan(/0x[0-9a-f]+/))
|
|
action { [:NUM, text.to_i(16)] }
|
|
|
|
when (text = @ss.scan(/\d+/))
|
|
action { [:NUM, text.to_i] }
|
|
|
|
when (text = @ss.scan(/[ ]+/))
|
|
action { }
|
|
|
|
when (text = @ss.scan(/\n/))
|
|
action { }
|
|
|
|
when (text = @ss.scan(/;/))
|
|
action { [:SEMICOLON,text] }
|
|
|
|
when (text = @ss.scan(/\(/))
|
|
action { [:LPAREN,text] }
|
|
|
|
when (text = @ss.scan(/\)/))
|
|
action { [:RPAREN,text] }
|
|
|
|
when (text = @ss.scan(/,/))
|
|
action { [:COMMA,text] }
|
|
|
|
when (text = @ss.scan(/:/))
|
|
action { [:COLON,text]}
|
|
|
|
when (text = @ss.scan(/=/))
|
|
action { [:EQUAL,text]}
|
|
|
|
when (text = @ss.scan(/\*/))
|
|
action { [:ASTERISK,text]}
|
|
|
|
when (text = @ss.scan(/\[/))
|
|
action { [:LBRACK,text]}
|
|
|
|
when (text = @ss.scan(/\]/))
|
|
action { [:RBRACK,text]}
|
|
|
|
when (text = @ss.scan(/\{/))
|
|
action { [:LCURL,text]}
|
|
|
|
when (text = @ss.scan(/\}/))
|
|
action { [:RCURL,text]}
|
|
|
|
when (text = @ss.scan(/\+/))
|
|
action { [:PLUS,text]}
|
|
|
|
when (text = @ss.scan(/-/))
|
|
action { [:MINUS,text]}
|
|
|
|
when (text = @ss.scan(/\|/))
|
|
action { [:PIPE,text]}
|
|
|
|
when (text = @ss.scan(/~/))
|
|
action { [:TILDE,text]}
|
|
|
|
when (text = @ss.scan(/>/))
|
|
action { [:GT,text]}
|
|
|
|
when (text = @ss.scan(/char/))
|
|
action { [:TYPE,text]}
|
|
|
|
when (text = @ss.scan(/short/))
|
|
action { [:TYPE,text]}
|
|
|
|
when (text = @ss.scan(/int/))
|
|
action { [:TYPE,text]}
|
|
|
|
when (text = @ss.scan(/long/))
|
|
action { [:TYPE,text]}
|
|
|
|
when (text = @ss.scan(/while/))
|
|
action { [:WHILE,text]}
|
|
|
|
when (text = @ss.scan(/for/))
|
|
action { [:FOR,text]}
|
|
|
|
when (text = @ss.scan(/extern/))
|
|
action { [:EXTERN,text]}
|
|
|
|
when (text = @ss.scan(/\w+/))
|
|
action { [:IDENT,text]}
|
|
|
|
when (text = @ss.scan(/./))
|
|
action { [:UNK,text]}
|
|
|
|
else
|
|
text = @ss.string[@ss.pos .. -1]
|
|
raise ScanError, "can not match: '" + text + "'"
|
|
end # if
|
|
|
|
else
|
|
raise ScanError, "undefined state: '" + state.to_s + "'"
|
|
end # case state
|
|
token
|
|
end # def _next_token
|
|
|
|
def tokenize(code)
|
|
scan_setup(code)
|
|
tokens = []
|
|
while token = next_token
|
|
tokens << token
|
|
end
|
|
tokens
|
|
end
|
|
def make_bytes(val)
|
|
bytes=[]
|
|
8.times do |i|
|
|
mask=0xFF << i*8
|
|
byte=(val&mask) >> i*8
|
|
bytes.push byte
|
|
end
|
|
return bytes
|
|
end
|
|
end # class
|