-
Notifications
You must be signed in to change notification settings - Fork 22
/
parserbase.rb
94 lines (77 loc) · 1.67 KB
/
parserbase.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
require 'scanner'
require 'tokens'
require 'pp'
require 'ast'
# Base-class for all Parsers.
# Defines some common methods for parsing sourcecode.
class ParserBase
include Tokens
include AST
# The constructor takes a Scanner instance as an argument
# to read the source code to parse from.
def initialize(scanner)
@scanner = scanner
end
def kleene
res = []
while e = yield
res << e
end
res
end
def position
@scanner.position
end
def literal(str)
@scanner.expect_str(str)
end
def expect(*args)
args.each do |a|
r = @scanner.expect(a)
return r if r
end
return nil
end
def keyword(arg)
Tokens::Keyword.expect(@scanner,arg)
end
def expected(name)
error("Expected: #{name}")
end
def nolfws
@scanner.nolfws
end
def ws
@scanner.ws
end
# Returns filename from which parser reads code.
def filename
@scanner.filename
end
# Returns true, if the parser gets code from a file.
def from_file?
end
# Output error message by raising an exception.
# Error message contains filename and linenumber, if reading from a file.
# Otherwise, the message only contains the current linenumber and the error message.
def error(message)
i = 0
str = ""
while (i < 30) && (c = @scanner.get)
str << c
i += 1
end
if from_file?
raise "Parse error: #{filename}(#{@scanner.lineno}): #{message}\nAfter: '#{str}'"
else
raise "Parse error: #{@scanner.lineno}: #{message}"
end
end
protected
# Protected accessor method for the scanner object.
# For use in subclasses.
def scanner
@scanner
end
end