Commit current state

This commit is contained in:
pjht 2019-06-23 10:40:25 -05:00
parent bacd68d1d9
commit 7a8b3f9c43
11 changed files with 1149 additions and 0 deletions

View File

@ -1,3 +1,4 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "rexical" gem "rexical"
gem "racc" gem "racc"
gem "rake"

View File

@ -2,6 +2,7 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
racc (1.4.14) racc (1.4.14)
rake (12.3.2)
rexical (1.0.5) rexical (1.0.5)
PLATFORMS PLATFORMS
@ -9,6 +10,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
racc racc
rake
rexical rexical
BUNDLED WITH BUNDLED WITH

7
Rakefile Normal file
View File

@ -0,0 +1,7 @@
task :default => ["lexer.rb","parser.rb"]
file "lexer.rb" => ["lexer.rex"] do
`rex lexer.rex -o lexer.rb`
end
file "parser.rb" => ["parser.y"] do
`racc parser.y -o parser.rb`
end

196
compiler Executable file
View File

@ -0,0 +1,196 @@
#! /usr/bin/env ruby
`rake`
require "./parser.rb"
$indx_map=-8
$var_map={}
$tab_level=-1
def generate_expr(expression)
$tab_level+=1
$tab_level.times do
print "-"
end
code=""
p expression
case expression[:type]
when :number
code+="mov rax,#{expression[:value]}\n"
when :neg
code+=generate_expr(expression[:expr])
code+="neg rax\n"
when :comp
code+=generate_expr(expression[:expr])
code+="not rax\n"
when :lneg
code+=generate_expr(expression[:expr])
code+="cmp rax,0\n"
code+="mov rax,0\n"
code+="sete al\n"
when :var
code+="mov rax,[rbp#{$var_map[expression[:name]][1]}]\n"
when :assign
code+=generate_expr(expression[:expr])
code+="mov [rbp#{$var_map[expression[:name]][1]}],rax\n"
when :comma
code+=generate_expr(expression[:expr1])
code+=generate_expr(expression[:expr2])
when :seteq
expression[:type]=expression[:op]
name=expression[:name]
expression.delete :op
expression.delete :name
code+=generate_expr({:type=>:assign,:name=>name,:expr=>expression})
else
code+=generate_expr(expression[:expr1])
code+="push rax\n"
code+=generate_expr(expression[:expr2])
code+="pop rcx\n"
case expression[:type]
when :plus
code+="add rax,rcx\n"
when :minus
code+="push rax\n"
code+="push rcx\n"
code+="pop rax\n"
code+="pop rcx\n"
code+="sub rax,rcx\n"
when :mul
code+="imul rax,rcx\n"
when :div
code+="push rax\n"
code+="push rcx\n"
code+="pop rax\n"
code+="pop rcx\n"
code+="mov edx,0\n"
code+="idiv ecx\n"
when :mod
code+="push rax\n"
code+="push rcx\n"
code+="pop rax\n"
code+="pop rcx\n"
code+="mov edx,0\n"
code+="idiv ecx\n"
code+="mov eax,edx\n"
when :eq
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="sete al\n"
when :ne
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="setne al\n"
when :ge
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="setge al\n"
when :le
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="setle al\n"
when :gt
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="setgt al\n"
when :lt
code+="cmp rax,rcx\n"
code+="mov rax,0\n"
code+="setlt al\n"
when :lor
code+="or eax,ecx\n"
code+="mov eax,0\n"
code+="setne al\n"
when :land
code+="cmp ecx,0\n"
code+="setne cl\n"
code+="cmp eax,0\n"
code+="mov eax,0\n"
code+="setne al\n"
code+="and al,cl\n"
when :shl
code+="push rax\n"
code+="push rcx\n"
code+="pop rax\n"
code+="pop rcx\n"
code+="shl rax,cl\n"
when :shr
code+="push rax\n"
code+="push rcx\n"
code+="pop rax\n"
code+="pop rcx\n"
code+="shr rax,cl\n"
when :and
code+="and rax,rcx\n"
when :or
code+="or rax,rcx\n"
when :xor
code+="xor rax,rcx\n"
end
end
$tab_level-=1
return code
end
def generate_statement(statement)
$tab_level+=1
$tab_level.times do
print "-"
end
p statement
code=""
case statement[:type]
when :return
code+=generate_expr(statement[:expr])
code+="mov rsp,rbp\n"
code+="pop rbp\n"
code+="ret\n"
when :vardecl
code+="push 0\n"
$var_map[statement[:varname]]=[statement[:vartype],$indx]
$indx-=8
when :vardeclinit
code+=generate_expr(statement[:init])
code+="push rax\n"
$var_map[statement[:varname]]=[statement[:vartype],$indx]
$indx-=8
when :expr
code+=generate_expr(statement[:expr])
end
$tab_level-=1;
return code
end
def generate_block(block)
code=""
for statement in block
code+=generate_statement(statement)
end
return code
end
def generate_func(func)
code=""
$indx=-8
$var_map={}
code+=".globl _#{func[:name]}\n"
code+="_#{func[:name]}:\n"
code+="push rbp\n"
code+="mov rbp,rsp\n"
code+=generate_block(func[:code])
code+="mov rax,0\n"
code+="mov rsp,rbp\n"
code+="pop rbp\n"
code+="ret\n"
return code
end
def generate(ast)
code=""
for func in ast
code+=generate_func(func)
end
return code
end
program=File.read("main.c")
p CX86.new.tokenize(program)
ast=CX86.new.parse(program)
code=generate(ast)
#puts code
f=File.open("out.asm","w")
f.puts code
f.close
puts `gcc -masm=intel -o out out.asm;./out;echo $?`

205
lexer.rb Normal file
View File

@ -0,0 +1,205 @@
#--
# DO NOT MODIFY!!!!
# This file is automatically generated by rex 1.0.5
# from lexical definition file "lexer.rex".
#++
require 'racc/parser'
class CX86 < 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(/int/))
action {[:TYPE,:INT]}
when (text = @ss.scan(/\(/))
action {[:OPEN_PAREN,"("]}
when (text = @ss.scan(/\)/))
action {[:CLOSE_PAREN,")"]}
when (text = @ss.scan(/\{/))
action {[:OPEN_CURLY,"{"]}
when (text = @ss.scan(/\}/))
action {[:CLOSE_CURLY,"}"]}
when (text = @ss.scan(/;/))
action {[:SEMICOLON,";"]}
when (text = @ss.scan(/-/))
action {[:MINUS,"-"]}
when (text = @ss.scan(/~/))
action {[:COMP,"~"]}
when (text = @ss.scan(/!/))
action {[:LNEG,"!"]}
when (text = @ss.scan(/\+=/))
action {[:SETEQ,:plus]}
when (text = @ss.scan(/\-\=/))
action {[:SETEQ,:minus]}
when (text = @ss.scan(/\/\=/))
action {[:SETEQ,:mul]}
when (text = @ss.scan(/\*\=/))
action {[:SETEQ,:div]}
when (text = @ss.scan(/\%\=/))
action {[:SETEQ,:mod]}
when (text = @ss.scan(/\<\<\=/))
action {[:SETEQ,:shl]}
when (text = @ss.scan(/\>\>\=/))
action {[:SETEQ,:shr]}
when (text = @ss.scan(/\&\=/))
action {[:SETEQ,:and]}
when (text = @ss.scan(/\|\=/))
action {[:SETEQ,:or]}
when (text = @ss.scan(/\^\=/))
action {[:SETEQ,:xor]}
when (text = @ss.scan(/\+/))
action {[:PLUS,"+"]}
when (text = @ss.scan(/\*/))
action {[:MUL,"*"]}
when (text = @ss.scan(/\//))
action {[:DIV,"/"]}
when (text = @ss.scan(/%/))
action {[:MOD,"%"]}
when (text = @ss.scan(/\&/))
action {[:AND,"&"]}
when (text = @ss.scan(/\|/))
action {[:OR,"|"]}
when (text = @ss.scan(/\^/))
action {[:XOR,"^"]}
when (text = @ss.scan(/<</))
action {[:SHL,"<<"]}
when (text = @ss.scan(/>>/))
action {[:SHR,">>"]}
when (text = @ss.scan(/\&\&/))
action {[:LAND,"&&"]}
when (text = @ss.scan(/\|\|/))
action {[:LOR,"||"]}
when (text = @ss.scan(/\=\=/))
action {[:EQ,"=="]}
when (text = @ss.scan(/\!\=/))
action {[:NE,"!="]}
when (text = @ss.scan(/\</))
action {[:LT,"<"]}
when (text = @ss.scan(/\<\=/))
action {[:LE,"<="]}
when (text = @ss.scan(/\>/))
action {[:GT,">"]}
when (text = @ss.scan(/\>\=/))
action {[:GE,">="]}
when (text = @ss.scan(/=/))
action {[:EQUALS,"="]}
when (text = @ss.scan(/,/))
action {[:COMMA,","]}
when (text = @ss.scan(/return/))
action {[:RETURN,"return"]}
when (text = @ss.scan(/\d+/))
action {[:NUM,text.to_i]}
when (text = @ss.scan(/\w+/))
action {[:IDENT,text]}
when (text = @ss.scan(/[ \t\n]+/))
action {}
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 # class
end

56
lexer.rex Normal file
View File

@ -0,0 +1,56 @@
class CX86
macro
BLANK [\ \t\n]+
rule
int {[:TYPE,:INT]}
\( {[:OPEN_PAREN,"("]}
\) {[:CLOSE_PAREN,")"]}
\{ {[:OPEN_CURLY,"{"]}
\} {[:CLOSE_CURLY,"}"]}
; {[:SEMICOLON,";"]}
- {[:MINUS,"-"]}
~ {[:COMP,"~"]}
! {[:LNEG,"!"]}
\+= {[:SETEQ,:plus]}
\-\= {[:SETEQ,:minus]}
\/\= {[:SETEQ,:mul]}
\*\= {[:SETEQ,:div]}
\%\= {[:SETEQ,:mod]}
\<\<\= {[:SETEQ,:shl]}
\>\>\= {[:SETEQ,:shr]}
\&\= {[:SETEQ,:and]}
\|\= {[:SETEQ,:or]}
\^\= {[:SETEQ,:xor]}
\+ {[:PLUS,"+"]}
\* {[:MUL,"*"]}
\/ {[:DIV,"/"]}
% {[:MOD,"%"]}
\& {[:AND,"&"]}
\| {[:OR,"|"]}
\^ {[:XOR,"^"]}
<< {[:SHL,"<<"]}
>> {[:SHR,">>"]}
\&\& {[:LAND,"&&"]}
\|\| {[:LOR,"||"]}
\=\= {[:EQ,"=="]}
\!\= {[:NE,"!="]}
\< {[:LT,"<"]}
\<\= {[:LE,"<="]}
\> {[:GT,">"]}
\>\= {[:GE,">="]}
= {[:EQUALS,"="]}
, {[:COMMA,","]}
return {[:RETURN,"return"]}
\d+ {[:NUM,text.to_i]}
\w+ {[:IDENT,text]}
{BLANK} {}
inner
def tokenize(code)
scan_setup(code)
tokens = []
while token = next_token
tokens << token
end
tokens
end
end

5
main.c Normal file
View File

@ -0,0 +1,5 @@
int main() {
int x=2;
x+=2;
return x;
}

BIN
out Executable file

Binary file not shown.

20
out.asm Normal file
View File

@ -0,0 +1,20 @@
.globl _main
_main:
push rbp
mov rbp,rsp
mov rax,2
push rax
mov rax,[rbp-8]
push rax
mov rax,2
pop rcx
add rax,rcx
mov [rbp-8],rax
mov rax,[rbp-8]
mov rsp,rbp
pop rbp
ret
mov rax,0
mov rsp,rbp
pop rbp
ret

593
parser.rb Normal file
View File

@ -0,0 +1,593 @@
#
# DO NOT MODIFY!!!!
# This file is automatically generated by Racc 1.4.14
# from Racc grammer file "".
#
require 'racc/parser.rb'
require "./lexer.rb"
class CX86 < Racc::Parser
module_eval(<<'...end parser.y/module_eval...', 'parser.y', 59)
def initialize()
@yydebug=true
end
def parse(input)
scan_str(input)
end
...end parser.y/module_eval...
##### State transition tables begin ###
racc_action_table = [
15, 22, 21, 71, 63, 47, 14, 39, 67, 17,
18, 19, 20, 15, 22, 21, 54, 55, 40, 14,
93, 36, 17, 18, 19, 20, 22, 21, 48, 33,
22, 21, 41, 41, 17, 18, 19, 20, 17, 18,
19, 20, 33, 41, 53, 41, 41, 53, 54, 55,
52, 22, 21, 52, 33, 22, 21, 41, 33, 17,
18, 19, 20, 17, 18, 19, 20, 22, 21, 56,
57, 58, 59, 60, 61, 17, 18, 19, 20, 33,
22, 21, 41, 33, 56, 57, 58, 59, 17, 18,
19, 20, 43, 21, 11, 33, 43, 21, 68, 69,
17, 18, 19, 20, 17, 18, 19, 20, 33, 43,
21, 54, 55, 43, 21, 54, 55, 17, 18, 19,
20, 17, 18, 19, 20, 43, 21, 54, 55, 43,
21, 60, 61, 17, 18, 19, 20, 17, 18, 19,
20, 43, 21, 9, 8, 43, 21, 7, 63, 17,
18, 19, 20, 17, 18, 19, 20, 43, 21, 64,
3, 43, 21, 65, 6, 17, 18, 19, 20, 17,
18, 19, 20, 43, 21, 3, 4, 43, 21, 62,
66, 17, 18, 19, 20, 17, 18, 19, 20, 43,
21, 65, 64, 43, 21, 62, nil, 17, 18, 19,
20, 17, 18, 19, 20, 43, 21, nil, nil, 43,
21, nil, nil, 17, 18, 19, 20, 17, 18, 19,
20, 43, 21, nil, nil, 43, 21, nil, nil, 17,
18, 19, 20, 17, 18, 19, 20, 43, 21, nil,
nil, 43, 21, nil, nil, 17, 18, 19, 20, 17,
18, 19, 20, 43, 21, 56, 57, 58, 59, 53,
nil, 17, 18, 19, 20, 52, 49, 50, 51, 49,
50, 51, 49, 50, 51 ]
racc_action_check = [
13, 13, 13, 46, 30, 22, 13, 15, 38, 13,
13, 13, 13, 11, 11, 11, 83, 83, 16, 11,
92, 12, 11, 11, 11, 11, 69, 69, 22, 13,
48, 48, 46, 38, 69, 69, 69, 69, 48, 48,
48, 48, 11, 16, 79, 92, 70, 80, 26, 26,
79, 47, 47, 80, 69, 21, 21, 72, 48, 47,
47, 47, 47, 21, 21, 21, 21, 14, 14, 85,
85, 85, 85, 28, 28, 14, 14, 14, 14, 47,
41, 41, 73, 21, 27, 27, 27, 27, 41, 41,
41, 41, 56, 56, 9, 14, 58, 58, 39, 39,
56, 56, 56, 56, 58, 58, 58, 58, 41, 59,
59, 81, 81, 60, 60, 82, 82, 59, 59, 59,
59, 60, 60, 60, 60, 66, 66, 84, 84, 18,
18, 87, 87, 66, 66, 66, 66, 18, 18, 18,
18, 19, 19, 8, 6, 20, 20, 4, 89, 19,
19, 19, 19, 20, 20, 20, 20, 61, 61, 90,
0, 49, 49, 91, 3, 61, 61, 61, 61, 49,
49, 49, 49, 50, 50, 2, 1, 51, 51, 88,
33, 50, 50, 50, 50, 51, 51, 51, 51, 52,
52, 32, 31, 53, 53, 29, nil, 52, 52, 52,
52, 53, 53, 53, 53, 54, 54, nil, nil, 55,
55, nil, nil, 54, 54, 54, 54, 55, 55, 55,
55, 57, 57, nil, nil, 65, 65, nil, nil, 57,
57, 57, 57, 65, 65, 65, 65, 64, 64, nil,
nil, 63, 63, nil, nil, 64, 64, 64, 64, 63,
63, 63, 63, 62, 62, 86, 86, 86, 86, 25,
nil, 62, 62, 62, 62, 25, 24, 24, 24, 77,
77, 77, 78, 78, 78 ]
racc_action_pointer = [
158, 176, 173, 161, 147, nil, 140, nil, 138, 88,
nil, 11, 14, -2, 64, 4, 9, nil, 126, 138,
142, 52, -5, nil, 251, 247, 29, 63, 48, 168,
-24, 163, 161, 148, nil, nil, nil, nil, -1, 89,
nil, 77, nil, nil, nil, nil, -2, 48, 27, 158,
170, 174, 186, 190, 202, 206, 89, 218, 93, 106,
110, 154, 250, 238, 234, 222, 122, nil, nil, 23,
12, nil, 23, 48, nil, nil, nil, 254, 257, 32,
35, 92, 96, -3, 108, 48, 234, 106, 152, 120,
130, 133, 11, nil ]
racc_action_default = [
-50, -50, -1, -50, -50, -2, -50, 94, -50, -50,
-3, -50, -50, -5, -50, -50, -50, -11, -50, -50,
-50, -50, -16, -17, -21, -24, -27, -32, -35, -37,
-39, -41, -43, -50, -45, -48, -4, -6, -50, -50,
-10, -50, -12, -16, -13, -14, -50, -50, -50, -50,
-50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
-50, -50, -50, -50, -50, -50, -50, -7, -8, -50,
-49, -15, -46, -47, -18, -19, -20, -22, -23, -25,
-26, -28, -29, -30, -31, -33, -34, -36, -38, -40,
-42, -44, -50, -9 ]
racc_goto_table = [
38, 1, 88, 5, 42, 44, 45, 46, 81, 82,
83, 84, 12, 89, 37, 79, 80, 85, 86, 77,
78, 90, 91, 10, 87, nil, nil, 70, nil, nil,
nil, nil, nil, 72, 73, 74, 75, 76, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 92 ]
racc_goto_check = [
6, 1, 13, 1, 7, 7, 7, 6, 10, 10,
10, 10, 4, 14, 4, 9, 9, 11, 11, 8,
8, 15, 16, 3, 12, nil, nil, 6, nil, nil,
nil, nil, nil, 6, 6, 7, 7, 7, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 6 ]
racc_goto_pointer = [
nil, 1, nil, 14, 1, nil, -14, -14, -33, -39,
-48, -43, -38, -61, -51, -44, -44, nil, nil ]
racc_goto_default = [
nil, nil, 2, nil, nil, 13, 16, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 34, 35 ]
racc_reduce_table = [
0, 0, :racc_error,
1, 36, :_reduce_1,
2, 36, :_reduce_2,
5, 37, :_reduce_3,
3, 38, :_reduce_4,
1, 39, :_reduce_5,
2, 39, :_reduce_6,
3, 40, :_reduce_7,
3, 40, :_reduce_8,
5, 40, :_reduce_9,
2, 40, :_reduce_10,
1, 42, :_reduce_11,
2, 42, :_reduce_12,
2, 42, :_reduce_13,
2, 42, :_reduce_14,
3, 42, :_reduce_15,
1, 42, :_reduce_16,
1, 43, :_reduce_none,
3, 43, :_reduce_18,
3, 43, :_reduce_19,
3, 43, :_reduce_20,
1, 44, :_reduce_none,
3, 44, :_reduce_22,
3, 44, :_reduce_23,
1, 45, :_reduce_none,
3, 45, :_reduce_25,
3, 45, :_reduce_26,
1, 46, :_reduce_none,
3, 46, :_reduce_28,
3, 46, :_reduce_29,
3, 46, :_reduce_30,
3, 46, :_reduce_31,
1, 47, :_reduce_none,
3, 47, :_reduce_33,
3, 47, :_reduce_34,
1, 48, :_reduce_none,
3, 48, :_reduce_36,
1, 49, :_reduce_none,
3, 49, :_reduce_38,
1, 50, :_reduce_none,
3, 50, :_reduce_40,
1, 51, :_reduce_none,
3, 51, :_reduce_42,
1, 52, :_reduce_none,
3, 52, :_reduce_44,
1, 53, :_reduce_none,
3, 53, :_reduce_46,
3, 53, :_reduce_47,
1, 41, :_reduce_none,
3, 41, :_reduce_49 ]
racc_reduce_n = 50
racc_shift_n = 94
racc_token_table = {
false => 0,
:error => 1,
:TYPE => 2,
:IDENT => 3,
:OPEN_PAREN => 4,
:CLOSE_PAREN => 5,
:OPEN_CURLY => 6,
:CLOSE_CURLY => 7,
:RETURN => 8,
:SEMICOLON => 9,
:EQUALS => 10,
:NUM => 11,
:MINUS => 12,
:COMP => 13,
:LNEG => 14,
:MUL => 15,
:DIV => 16,
:MOD => 17,
:PLUS => 18,
:SHL => 19,
:SHR => 20,
:LT => 21,
:GT => 22,
:LE => 23,
:GE => 24,
:NE => 25,
:EQ => 26,
:AND => 27,
:XOR => 28,
:OR => 29,
:LAND => 30,
:exp => 31,
:LOR => 32,
:SETEQ => 33,
:COMMA => 34 }
racc_nt_base = 35
racc_use_result_var = true
Racc_arg = [
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_token_to_s_table = [
"$end",
"error",
"TYPE",
"IDENT",
"OPEN_PAREN",
"CLOSE_PAREN",
"OPEN_CURLY",
"CLOSE_CURLY",
"RETURN",
"SEMICOLON",
"EQUALS",
"NUM",
"MINUS",
"COMP",
"LNEG",
"MUL",
"DIV",
"MOD",
"PLUS",
"SHL",
"SHR",
"LT",
"GT",
"LE",
"GE",
"NE",
"EQ",
"AND",
"XOR",
"OR",
"LAND",
"exp",
"LOR",
"SETEQ",
"COMMA",
"$start",
"program",
"function",
"block",
"statements",
"statement",
"expression",
"factor",
"term",
"additivexp",
"shiftexp",
"relationalexp",
"equalityexp",
"andexp",
"xorexp",
"orexp",
"landexp",
"lorexp",
"assignexp" ]
Racc_debug_parser = false
##### State transition tables end #####
# reduce 0 omitted
module_eval(<<'.,.,', 'parser.y', 2)
def _reduce_1(val, _values, result)
result=[val[0]]
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 3)
def _reduce_2(val, _values, result)
result=[val[0],val[1]].flatten
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 4)
def _reduce_3(val, _values, result)
result={:type=>val[0],:name=>val[1],:code=>val[4]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 5)
def _reduce_4(val, _values, result)
result=val[1]
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 6)
def _reduce_5(val, _values, result)
result=[val[0]]
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 7)
def _reduce_6(val, _values, result)
result=[val[0],val[1]].flatten
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 8)
def _reduce_7(val, _values, result)
result={:type=>:return,:expr=>val[1]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 9)
def _reduce_8(val, _values, result)
result={:type=>:vardecl,:vartype=>val[0],:varname=>val[1]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 10)
def _reduce_9(val, _values, result)
result={:type=>:vardeclinit,:vartype=>val[0],:varname=>val[1],:init=>val[3]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 11)
def _reduce_10(val, _values, result)
result={:type=>:expr,:expr=>val[0]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 12)
def _reduce_11(val, _values, result)
result={:type=>:number,:value=>val[0]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 13)
def _reduce_12(val, _values, result)
result={:type=>:neg,:expr=>val[1]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 14)
def _reduce_13(val, _values, result)
result={:type=>:comp,:expr=>val[1]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 15)
def _reduce_14(val, _values, result)
result={:type=>:lneg,:expr=>val[1]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 16)
def _reduce_15(val, _values, result)
result=val[1]
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 17)
def _reduce_16(val, _values, result)
result={:type=>:var,:name=>val[0]}
result
end
.,.,
# reduce 17 omitted
module_eval(<<'.,.,', 'parser.y', 19)
def _reduce_18(val, _values, result)
result={:type=>:mul,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 20)
def _reduce_19(val, _values, result)
result={:type=>:div,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 21)
def _reduce_20(val, _values, result)
result={:type=>:mod,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 21 omitted
module_eval(<<'.,.,', 'parser.y', 23)
def _reduce_22(val, _values, result)
result={:type=>:plus,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 24)
def _reduce_23(val, _values, result)
result={:type=>:minus,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 24 omitted
module_eval(<<'.,.,', 'parser.y', 26)
def _reduce_25(val, _values, result)
result={:type=>:shl,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 27)
def _reduce_26(val, _values, result)
result={:type=>:shr,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 27 omitted
module_eval(<<'.,.,', 'parser.y', 29)
def _reduce_28(val, _values, result)
result={:type=>:lt,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 30)
def _reduce_29(val, _values, result)
result={:type=>:gt,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 31)
def _reduce_30(val, _values, result)
result={:type=>:le,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 32)
def _reduce_31(val, _values, result)
result={:type=>:ge,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 32 omitted
module_eval(<<'.,.,', 'parser.y', 34)
def _reduce_33(val, _values, result)
result={:type=>:ne,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 35)
def _reduce_34(val, _values, result)
result={:type=>:eq,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 35 omitted
module_eval(<<'.,.,', 'parser.y', 37)
def _reduce_36(val, _values, result)
result={:type=>:and,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 37 omitted
module_eval(<<'.,.,', 'parser.y', 39)
def _reduce_38(val, _values, result)
result={:type=>:xor,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 39 omitted
module_eval(<<'.,.,', 'parser.y', 41)
def _reduce_40(val, _values, result)
result={:type=>:or,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 41 omitted
module_eval(<<'.,.,', 'parser.y', 43)
def _reduce_42(val, _values, result)
result={:type=>:land,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 43 omitted
module_eval(<<'.,.,', 'parser.y', 45)
def _reduce_44(val, _values, result)
result={:type=>:lor,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
# reduce 45 omitted
module_eval(<<'.,.,', 'parser.y', 47)
def _reduce_46(val, _values, result)
result={:type=>:assign,:name=>val[0],:expr=>val[2]}
result
end
.,.,
module_eval(<<'.,.,', 'parser.y', 48)
def _reduce_47(val, _values, result)
result={:type=>:assign,:name=>val[0],:expr=>{:type=>val[1],:expr1=>{:type=>:var,:name=>val[0]},:expr2=>val[2]}}
result
end
.,.,
# reduce 48 omitted
module_eval(<<'.,.,', 'parser.y', 50)
def _reduce_49(val, _values, result)
result={:type=>:comma,:expr1=>val[0],:expr2=>val[2]}
result
end
.,.,
def _reduce_none(val, _values, result)
val[0]
end
end # class CX86

64
parser.y Normal file
View File

@ -0,0 +1,64 @@
class CX86
rule
program: function {result=[val[0]]}
| function program {result=[val[0],val[1]].flatten}
function: TYPE IDENT OPEN_PAREN CLOSE_PAREN block {result={:type=>val[0],:name=>val[1],:code=>val[4]}}
block: OPEN_CURLY statements CLOSE_CURLY {result=val[1]}
statements: statement {result=[val[0]]}
| statement statements {result=[val[0],val[1]].flatten}
statement: RETURN expression SEMICOLON {result={:type=>:return,:expr=>val[1]}}
| TYPE IDENT SEMICOLON {result={:type=>:vardecl,:vartype=>val[0],:varname=>val[1]}}
| TYPE IDENT EQUALS expression SEMICOLON {result={:type=>:vardeclinit,:vartype=>val[0],:varname=>val[1],:init=>val[3]}}
| expression SEMICOLON {result={:type=>:expr,:expr=>val[0]}}
factor: NUM {result={:type=>:number,:value=>val[0]}}
| MINUS factor {result={:type=>:neg,:expr=>val[1]}}
| COMP factor {result={:type=>:comp,:expr=>val[1]}}
| LNEG factor {result={:type=>:lneg,:expr=>val[1]}}
| OPEN_PAREN expression CLOSE_PAREN {result=val[1]}
| IDENT {result={:type=>:var,:name=>val[0]}}
term: factor
| term MUL factor {result={:type=>:mul,:expr1=>val[0],:expr2=>val[2]}}
| term DIV factor {result={:type=>:div,:expr1=>val[0],:expr2=>val[2]}}
| term MOD factor {result={:type=>:mod,:expr1=>val[0],:expr2=>val[2]}}
additivexp: term
| additivexp PLUS term {result={:type=>:plus,:expr1=>val[0],:expr2=>val[2]}}
| additivexp MINUS term {result={:type=>:minus,:expr1=>val[0],:expr2=>val[2]}}
shiftexp: additivexp
| shiftexp SHL additivexp {result={:type=>:shl,:expr1=>val[0],:expr2=>val[2]}}
| shiftexp SHR additivexp {result={:type=>:shr,:expr1=>val[0],:expr2=>val[2]}}
relationalexp: shiftexp
| relationalexp LT shiftexp {result={:type=>:lt,:expr1=>val[0],:expr2=>val[2]}}
| relationalexp GT shiftexp {result={:type=>:gt,:expr1=>val[0],:expr2=>val[2]}}
| relationalexp LE shiftexp {result={:type=>:le,:expr1=>val[0],:expr2=>val[2]}}
| relationalexp GE shiftexp {result={:type=>:ge,:expr1=>val[0],:expr2=>val[2]}}
equalityexp: relationalexp
| equalityexp NE relationalexp {result={:type=>:ne,:expr1=>val[0],:expr2=>val[2]}}
| equalityexp EQ relationalexp {result={:type=>:eq,:expr1=>val[0],:expr2=>val[2]}}
andexp: equalityexp
| andexp AND equalityexp {result={:type=>:and,:expr1=>val[0],:expr2=>val[2]}}
xorexp: andexp
| xorexp XOR andexp {result={:type=>:xor,:expr1=>val[0],:expr2=>val[2]}}
orexp: xorexp
| orexp OR xorexp {result={:type=>:or,:expr1=>val[0],:expr2=>val[2]}}
landexp: orexp
| landexp LAND orexp {result={:type=>:land,:expr1=>val[0],:expr2=>val[2]}}
lorexp: landexp
| exp LOR landexp {result={:type=>:lor,:expr1=>val[0],:expr2=>val[2]}}
assignexp: lorexp
| IDENT EQUALS expression {result={:type=>:assign,:name=>val[0],:expr=>val[2]}}
| IDENT SETEQ expression {result={:type=>:assign,:name=>val[0],:expr=>{:type=>val[1],:expr1=>{:type=>:var,:name=>val[0]},:expr2=>val[2]}}}
expression: assignexp
| expression COMMA expression {result={:type=>:comma,:expr1=>val[0],:expr2=>val[2]}}
end
---- header
require "./lexer.rb"
---- inner
def initialize()
@yydebug=true
end
def parse(input)
scan_str(input)
end