-
Notifications
You must be signed in to change notification settings - Fork 1
/
sample.rb
119 lines (97 loc) · 2.44 KB
/
sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
require "pitacc"
require "pitacc/ll1"
class MyParser < PitaCC::Parser
set_engine :LL1
uppercase_is_nonterminal
# lowercase_is_terminal
def parse lex
@buf = []
super
return @buf
end
rules {
rule :EXPR, :TERM, :"EXPR'"
rule :"EXPR'", :OP1, :EXPR do|op, e|
@buf << op
end
rule :OP1, :+
rule :OP1, :-
rule :"EXPR'" # ε
rule :TERM, :FACTOR, :"TERM'"
rule :"TERM'", :OP2, :TERM do|op, t|
@buf << op
end
rule :OP2, :*
rule :OP2, :/
rule :"TERM'" # ε
rule :FACTOR, :num do|n|
@buf << n
end
rule :FACTOR, :"(", :EXPR, :")"
}
end
class Token
attr_accessor :sym, :val
end
class Lex
def initialize
@buf = "2 * (1 - 6) / (3 + 5)"
@current = nil
end
def peek
if @current then
return @current
end
next_token
return @current
end
def get
if @current then
tmp = @current
@current = nil
return tmp
end
next_token
tmp = @current
@current = nil
return tmp
end
def next_token
token = Token.new
@current = token
if m = /\A\s+/.match(@buf) then
@buf[0, m[0].length] = ""
end
case
when m = /\A\z/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = "$"
when m = /\A\(/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :"("
when m = /\A\)/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :")"
when m = /\A\+/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :+
when m = /\A\-/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :-
when m = /\A\*/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :*
when m = /\A\//.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :/
when m = /\A\d+/.match(@buf) then
@buf[0, m[0].length] = ""
token.sym = :num
token.val = m[0].to_i
else
raise "lex error"
end
end
end
parser = MyParser.new
p parser.parse Lex.new