dhaka 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/dhaka.rb +24 -22
- data/lib/evaluator/evaluator.rb +42 -44
- data/lib/grammar/closure_hash.rb +4 -3
- data/lib/grammar/grammar.rb +113 -110
- data/lib/grammar/grammar_symbol.rb +6 -3
- data/lib/grammar/precedence.rb +3 -2
- data/lib/grammar/production.rb +5 -6
- data/lib/parser/action.rb +16 -11
- data/lib/parser/channel.rb +22 -16
- data/lib/parser/compiled_parser.rb +28 -22
- data/lib/parser/conflict.rb +54 -0
- data/lib/parser/item.rb +19 -19
- data/lib/parser/parse_result.rb +16 -1
- data/lib/parser/parse_tree.rb +15 -9
- data/lib/parser/parser.rb +51 -80
- data/lib/parser/parser_run.rb +6 -6
- data/lib/parser/parser_state.rb +16 -18
- data/lib/parser/token.rb +6 -4
- data/lib/tokenizer/tokenizer.rb +34 -31
- data/test/all_tests.rb +4 -18
- data/test/another_lalr_but_not_slr_grammar.rb +9 -5
- data/test/{arithmetic_evaluator.rb → arithmetic/arithmetic_evaluator.rb} +1 -2
- data/test/{arithmetic_evaluator_test.rb → arithmetic/arithmetic_evaluator_test.rb} +9 -20
- data/test/arithmetic/arithmetic_grammar.rb +41 -0
- data/test/{arithmetic_grammar_test.rb → arithmetic/arithmetic_grammar_test.rb} +2 -4
- data/test/{arithmetic_test_methods.rb → arithmetic/arithmetic_test_methods.rb} +1 -3
- data/test/{arithmetic_tokenizer.rb → arithmetic/arithmetic_tokenizer.rb} +8 -10
- data/test/{arithmetic_tokenizer_test.rb → arithmetic/arithmetic_tokenizer_test.rb} +4 -2
- data/test/{arithmetic_precedence_evaluator.rb → arithmetic_precedence/arithmetic_precedence_evaluator.rb} +1 -2
- data/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +24 -0
- data/test/{arithmetic_precedence_grammar_test.rb → arithmetic_precedence/arithmetic_precedence_grammar_test.rb} +2 -3
- data/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +31 -0
- data/test/{arithmetic_precedence_tokenizer.rb → arithmetic_precedence/arithmetic_precedence_tokenizer.rb} +8 -10
- data/test/brackets/bracket_grammar.rb +23 -0
- data/test/{bracket_tokenizer.rb → brackets/bracket_tokenizer.rb} +2 -4
- data/test/{brackets_test.rb → brackets/brackets_test.rb} +3 -4
- data/test/chittagong/chittagong_driver.rb +47 -0
- data/test/{chittagong_driver_test.rb → chittagong/chittagong_driver_test.rb} +66 -58
- data/test/{chittagong_evaluator.rb → chittagong/chittagong_evaluator.rb} +28 -13
- data/test/{chittagong_evaluator_test.rb → chittagong/chittagong_evaluator_test.rb} +6 -10
- data/test/chittagong/chittagong_grammar.rb +110 -0
- data/test/{chittagong_parser_test.rb → chittagong/chittagong_parser_test.rb} +5 -7
- data/test/{chittagong_test.rb → chittagong/chittagong_test.rb} +27 -36
- data/test/{chittagong_tokenizer.rb → chittagong/chittagong_tokenizer.rb} +17 -17
- data/test/{chittagong_tokenizer_test.rb → chittagong/chittagong_tokenizer_test.rb} +2 -3
- data/test/compiled_parser_test.rb +9 -42
- data/test/dhaka_test_helper.rb +17 -0
- data/test/evaluator_test.rb +18 -3
- data/test/grammar_test.rb +10 -15
- data/test/lalr_but_not_slr_grammar.rb +10 -8
- data/test/malformed_grammar.rb +2 -4
- data/test/malformed_grammar_test.rb +2 -3
- data/test/nullable_grammar.rb +11 -8
- data/test/parse_result_test.rb +44 -0
- data/test/parser_state_test.rb +36 -0
- data/test/parser_test.rb +53 -103
- data/test/precedence_grammar.rb +6 -6
- data/test/precedence_grammar_test.rb +2 -3
- data/test/rr_conflict_grammar.rb +5 -7
- data/test/simple_grammar.rb +6 -8
- data/test/sr_conflict_grammar.rb +6 -6
- metadata +30 -26
- data/test/arithmetic_grammar.rb +0 -35
- data/test/arithmetic_precedence_grammar.rb +0 -24
- data/test/arithmetic_precedence_parser_test.rb +0 -33
- data/test/bracket_grammar.rb +0 -25
- data/test/chittagong_grammar.rb +0 -104
- data/test/incomplete_arithmetic_evaluator.rb +0 -60
data/test/all_tests.rb
CHANGED
@@ -1,19 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
|
6
|
-
require 'evaluator_test'
|
7
|
-
require 'compiled_parser_test'
|
8
|
-
require 'arithmetic_evaluator_test'
|
9
|
-
require 'arithmetic_grammar_test'
|
10
|
-
require 'arithmetic_tokenizer_test'
|
11
|
-
require 'arithmetic_precedence_grammar_test'
|
12
|
-
require 'arithmetic_precedence_parser_test'
|
13
|
-
require 'brackets_test'
|
14
|
-
require 'precedence_grammar_test'
|
15
|
-
require 'chittagong_parser_test'
|
16
|
-
require 'chittagong_evaluator_test'
|
17
|
-
require 'chittagong_tokenizer_test'
|
18
|
-
require 'chittagong_test'
|
19
|
-
require 'chittagong_driver_test'
|
2
|
+
Dir['**/*test.rb'].each do |test_file|
|
3
|
+
puts test_file
|
4
|
+
require File.join(File.dirname(__FILE__), test_file)
|
5
|
+
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
require File.dirname(__FILE__)+'/../lib/dhaka'
|
2
2
|
|
3
3
|
class AnotherLALRButNotSLRGrammar < Dhaka::Grammar
|
4
|
+
|
4
5
|
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
5
|
-
assignment
|
6
|
-
rhs
|
6
|
+
assignment %w| L = R |
|
7
|
+
rhs %w| R |
|
7
8
|
end
|
9
|
+
|
8
10
|
for_symbol('L') do
|
9
|
-
contents
|
10
|
-
identifier
|
11
|
+
contents %w| * R |
|
12
|
+
identifier %w| id |
|
11
13
|
end
|
14
|
+
|
12
15
|
for_symbol('R') do
|
13
|
-
l_value
|
16
|
+
l_value %w| L |
|
14
17
|
end
|
18
|
+
|
15
19
|
end
|
16
20
|
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require '
|
2
|
-
require 'arithmetic_evaluator'
|
3
|
-
require 'arithmetic_test_methods'
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/arithmetic_evaluator'
|
3
|
+
require File.dirname(__FILE__) + '/arithmetic_test_methods'
|
4
4
|
eval(Dhaka::Parser.new(ArithmeticGrammar).compile_to_ruby_source_as(:CompiledArithmeticParser))
|
5
|
+
|
5
6
|
class TestArithmeticEvaluator < Test::Unit::TestCase
|
6
7
|
include ArithmeticTestMethods
|
7
8
|
|
@@ -10,45 +11,33 @@ class TestArithmeticEvaluator < Test::Unit::TestCase
|
|
10
11
|
@max_func = Proc.new {|args| args.inject {|max, elem| max = (elem > max ? elem : max)}}
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
14
|
def test_results_simple_arithmetic_given_tokens_and_parse_tree_1
|
15
|
-
|
16
15
|
token_stream = [token('n', 2), token('-', nil), token('n', 4), token(Dhaka::END_SYMBOL_NAME, nil)]
|
17
|
-
parse_tree
|
16
|
+
parse_tree = parse(token_stream)
|
18
17
|
assert_equal -2, ArithmeticEvaluator.new(@min_func, @max_func).evaluate(parse_tree)
|
19
|
-
|
20
18
|
end
|
21
19
|
|
22
20
|
def test_results_simple_arithmetic_given_tokens_and_parse_tree_2
|
23
|
-
|
24
21
|
token_stream = [token('n', 2), token('-', nil), token('(', nil), token('n', 3), token('/', nil), token('n', 4), token(')', nil), token(Dhaka::END_SYMBOL_NAME, nil)]
|
25
|
-
parse_tree
|
22
|
+
parse_tree = parse(token_stream)
|
26
23
|
assert_equal 1.25, ArithmeticEvaluator.new(@min_func, @max_func).evaluate(parse_tree)
|
27
|
-
|
28
24
|
end
|
29
25
|
|
30
26
|
def test_results_simple_arithmetic_given_tokens_and_parse_tree_3
|
31
|
-
|
32
27
|
token_stream = [token('n', 2), token('+', nil), token('(', nil), token('n', 3), token('/', nil), token('(', nil), token('n', 7), token('-', nil), token('n', 5), token(')', nil) , token(')', nil), token(Dhaka::END_SYMBOL_NAME, nil)]
|
33
|
-
parse_tree
|
28
|
+
parse_tree = parse(token_stream)
|
34
29
|
assert_equal 3.5, ArithmeticEvaluator.new(@min_func, @max_func).evaluate(parse_tree)
|
35
|
-
|
36
30
|
end
|
37
31
|
|
38
32
|
def test_results_simple_arithmetic_given_tokens_and_parse_tree_4
|
39
|
-
|
40
33
|
token_stream = [token('n', 2), token('+', nil), token('h', nil), token('(', nil), token('n', 3), token(',', nil), token('n', 4), token(')', nil), token(Dhaka::END_SYMBOL_NAME, nil)]
|
41
|
-
parse_tree
|
34
|
+
parse_tree = parse(token_stream)
|
42
35
|
assert_equal 6, ArithmeticEvaluator.new(@min_func, @max_func).evaluate(parse_tree)
|
43
|
-
|
44
36
|
end
|
45
37
|
|
46
38
|
def test_results_simple_arithmetic_given_tokens_and_parse_tree_5
|
47
|
-
|
48
39
|
token_stream = [token('n', 2), token('+', nil), token('l', nil), token('(', nil), token('n', 3), token(',', nil), token('n', 4), token(')', nil), token(Dhaka::END_SYMBOL_NAME, nil)]
|
49
|
-
parse_tree
|
40
|
+
parse_tree = parse(token_stream)
|
50
41
|
assert_equal 5, ArithmeticEvaluator.new(@min_func, @max_func).evaluate(parse_tree)
|
51
|
-
|
52
42
|
end
|
53
|
-
|
54
43
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class ArithmeticGrammar < Dhaka::Grammar
|
2
|
+
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
4
|
+
expression %w| E |
|
5
|
+
end
|
6
|
+
|
7
|
+
for_symbol('E') do
|
8
|
+
subtraction %w| E - T |
|
9
|
+
addition %w| E + T |
|
10
|
+
term %w| T |
|
11
|
+
end
|
12
|
+
|
13
|
+
for_symbol('T') do
|
14
|
+
factor %w| F |
|
15
|
+
division %w| T / F |
|
16
|
+
multiplication %w| T * F |
|
17
|
+
end
|
18
|
+
|
19
|
+
for_symbol('F') do
|
20
|
+
getting_literals %w| n |
|
21
|
+
unpacking_parenthetized_expression %w| ( E ) |
|
22
|
+
function %w| Function |
|
23
|
+
end
|
24
|
+
|
25
|
+
for_symbol('Function') do
|
26
|
+
evaluating_function %w| FunctionName ( Args ) |
|
27
|
+
end
|
28
|
+
|
29
|
+
for_symbol('FunctionName') do
|
30
|
+
max_function %w| h |
|
31
|
+
min_function %w| l |
|
32
|
+
end
|
33
|
+
|
34
|
+
for_symbol('Args') do
|
35
|
+
empty_args %w||
|
36
|
+
single_args %w| E |
|
37
|
+
concatenating_args %w| E , Args |
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
@@ -1,11 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require 'arithmetic_grammar'
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/arithmetic_grammar'
|
3
3
|
|
4
4
|
class ArithmeticGrammarTest < Test::Unit::TestCase
|
5
|
-
|
6
5
|
def test_first_with_nullable_non_terminals
|
7
6
|
grammar = ArithmeticGrammar
|
8
7
|
assert_equal(Set.new(['(', 'n', 'h', 'l']), Set.new(grammar.first(grammar.symbol_for_name('Args')).collect { |symbol| symbol.name }))
|
9
8
|
end
|
10
|
-
|
11
9
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
module ArithmeticTestMethods
|
2
|
-
|
3
2
|
def parse(token_stream)
|
4
|
-
CompiledArithmeticParser.parse(token_stream)
|
3
|
+
CompiledArithmeticParser.parse(token_stream)
|
5
4
|
end
|
6
5
|
|
7
6
|
def token(symbol_name, value)
|
8
7
|
Dhaka::Token.new(symbol_name, value, nil)
|
9
8
|
end
|
10
|
-
|
11
9
|
end
|
@@ -1,15 +1,13 @@
|
|
1
|
-
require File.dirname(__FILE__)+'
|
2
|
-
require 'arithmetic_grammar'
|
3
|
-
|
1
|
+
require File.dirname(__FILE__) + '/arithmetic_grammar'
|
4
2
|
|
5
3
|
class ArithmeticTokenizer < Dhaka::Tokenizer
|
6
4
|
|
7
|
-
digits
|
8
|
-
parenths
|
9
|
-
operators
|
10
|
-
functions
|
11
|
-
arg_separator =
|
12
|
-
whitespace
|
5
|
+
digits = ('0'..'9').to_a
|
6
|
+
parenths = %w| ( ) |
|
7
|
+
operators = %w| - + / * |
|
8
|
+
functions = %w| h l |
|
9
|
+
arg_separator = %w| , |
|
10
|
+
whitespace = [' ']
|
13
11
|
|
14
12
|
all_characters = digits + parenths + operators + functions + arg_separator + whitespace
|
15
13
|
|
@@ -32,7 +30,7 @@ class ArithmeticTokenizer < Dhaka::Tokenizer
|
|
32
30
|
switch_to Dhaka::TOKENIZER_IDLE_STATE
|
33
31
|
end
|
34
32
|
for_characters digits do
|
35
|
-
curr_token.value
|
33
|
+
curr_token.value << curr_char
|
36
34
|
advance
|
37
35
|
end
|
38
36
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
require
|
2
|
-
require "arithmetic_tokenizer"
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + "/arithmetic_tokenizer"
|
3
3
|
|
4
4
|
class TestArithmeticTokenizer < Test::Unit::TestCase
|
5
5
|
def test_returns_end_of_input_token_for_empty_input
|
6
6
|
assert_equal([token(Dhaka::END_SYMBOL_NAME, nil)], ArithmeticTokenizer.tokenize([]).to_a)
|
7
7
|
end
|
8
|
+
|
8
9
|
def test_tokenizes_given_a_string_input
|
9
10
|
assert_equal([token('n', 2), token('-', nil), token('n', 4), token(Dhaka::END_SYMBOL_NAME, nil)], ArithmeticTokenizer.tokenize('2 - 4').to_a)
|
10
11
|
end
|
12
|
+
|
11
13
|
def test_a_longer_input
|
12
14
|
actual = ArithmeticTokenizer.tokenize('2+(3 / (7 - 5))').to_a
|
13
15
|
assert_equal([token('n', 2), token('+', nil), token('(', nil), token('n', 3), token('/', nil), token('(', nil), token('n', 7), token('-', nil), token('n', 5), token(')', nil) , token(')', nil), token(Dhaka::END_SYMBOL_NAME, nil)], actual)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ArithmeticPrecedenceGrammar < Dhaka::Grammar
|
2
|
+
|
3
|
+
precedences do
|
4
|
+
left %w| + - |
|
5
|
+
left %w| * / |
|
6
|
+
nonassoc %w| ^ |
|
7
|
+
end
|
8
|
+
|
9
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
10
|
+
expression %w| E |
|
11
|
+
end
|
12
|
+
|
13
|
+
for_symbol('E') do
|
14
|
+
addition %w| E + E |
|
15
|
+
subtraction %w| E - E |
|
16
|
+
multiplication %w| E * E |
|
17
|
+
division %w| E / E |
|
18
|
+
power %w| E ^ E |
|
19
|
+
literal %w| n |
|
20
|
+
parenthetized_expression %w| ( E ) |
|
21
|
+
negated_expression %w| - E |, :prec => '*'
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require 'arithmetic_precedence_grammar'
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/arithmetic_precedence_grammar'
|
3
3
|
|
4
4
|
class TestArithmeticPrecedenceGrammar < Test::Unit::TestCase
|
5
|
-
|
6
5
|
def setup
|
7
6
|
@addop = ArithmeticPrecedenceGrammar.symbol_for_name('+')
|
8
7
|
@subop = ArithmeticPrecedenceGrammar.symbol_for_name('-')
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + "/arithmetic_precedence_grammar"
|
3
|
+
require File.dirname(__FILE__) + "/arithmetic_precedence_tokenizer"
|
4
|
+
require File.dirname(__FILE__) + "/arithmetic_precedence_evaluator"
|
5
|
+
|
6
|
+
class TestArithmeticPrecedenceParser < Test::Unit::TestCase
|
7
|
+
def test_parses_arithmetic_expressions
|
8
|
+
fake_logger = FakeLogger.new
|
9
|
+
parser = Dhaka::Parser.new(ArithmeticPrecedenceGrammar, fake_logger)
|
10
|
+
eval(parser.compile_to_ruby_source_as(:ArithmeticPrecedenceParser))
|
11
|
+
|
12
|
+
assert_equal(30, fake_logger.warnings.size)
|
13
|
+
assert_equal(0, fake_logger.errors.size)
|
14
|
+
|
15
|
+
assert_equal(-8, evaluate(parse("5 * -14/(2*7 - 7) + 2")))
|
16
|
+
assert_equal(-4, evaluate(parse("-2^2")))
|
17
|
+
assert_equal(10, evaluate(parse("2+2^3")))
|
18
|
+
assert_equal(64, evaluate(parse("(2+2)^3")))
|
19
|
+
assert_equal(128, evaluate(parse("(2+2)^3*2")))
|
20
|
+
assert(parse("(2+2)^3^2").has_error?)
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse(input)
|
24
|
+
ArithmeticPrecedenceParser.parse(ArithmeticPrecedenceTokenizer.tokenize(input))
|
25
|
+
end
|
26
|
+
|
27
|
+
def evaluate(parse_tree)
|
28
|
+
ArithmeticPrecedenceEvaluator.new.evaluate(parse_tree)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -1,15 +1,13 @@
|
|
1
|
-
require File.dirname(__FILE__)+'
|
2
|
-
require 'arithmetic_precedence_grammar'
|
3
|
-
|
1
|
+
require File.dirname(__FILE__) + '/arithmetic_precedence_grammar'
|
4
2
|
|
5
3
|
class ArithmeticPrecedenceTokenizer < Dhaka::Tokenizer
|
6
4
|
|
7
|
-
digits
|
8
|
-
parenths
|
9
|
-
operators
|
10
|
-
functions
|
11
|
-
arg_separator =
|
12
|
-
whitespace
|
5
|
+
digits = ('0'..'9').to_a
|
6
|
+
parenths = %w| ( ) |
|
7
|
+
operators = %w| - + / * ^ |
|
8
|
+
functions = %w| h l |
|
9
|
+
arg_separator = %w| , |
|
10
|
+
whitespace = [' ']
|
13
11
|
|
14
12
|
all_characters = digits + parenths + operators + functions + arg_separator + whitespace
|
15
13
|
|
@@ -32,7 +30,7 @@ class ArithmeticPrecedenceTokenizer < Dhaka::Tokenizer
|
|
32
30
|
switch_to Dhaka::TOKENIZER_IDLE_STATE
|
33
31
|
end
|
34
32
|
for_characters digits do
|
35
|
-
curr_token.value
|
33
|
+
curr_token.value << curr_char
|
36
34
|
advance
|
37
35
|
end
|
38
36
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class BracketGrammar < Dhaka::Grammar
|
2
|
+
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
4
|
+
start %w| Package |
|
5
|
+
end
|
6
|
+
|
7
|
+
for_symbol('Package') do
|
8
|
+
soft_wrapped_package %w| ( Contents ) |
|
9
|
+
cardboard_package %w| [ Contents ] |
|
10
|
+
wooden_package %w| { Contents } |
|
11
|
+
end
|
12
|
+
|
13
|
+
for_symbol('Contents') do
|
14
|
+
bracket %w| B |
|
15
|
+
set_of_packages %w| SetOfPackages |
|
16
|
+
end
|
17
|
+
|
18
|
+
for_symbol('SetOfPackages') do
|
19
|
+
one_package %w| Package |
|
20
|
+
multiple_packages %w| SetOfPackages Package |
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -1,10 +1,8 @@
|
|
1
|
-
require File.dirname(__FILE__)+'
|
2
|
-
require 'bracket_grammar'
|
3
|
-
|
1
|
+
require File.dirname(__FILE__) + '/bracket_grammar'
|
4
2
|
|
5
3
|
class BracketTokenizer < Dhaka::Tokenizer
|
6
4
|
|
7
|
-
all_characters =
|
5
|
+
all_characters = %w| ( [ { B } ] ) |
|
8
6
|
|
9
7
|
for_state Dhaka::TOKENIZER_IDLE_STATE do
|
10
8
|
for_characters(all_characters) do
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'bracket_tokenizer'
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
2
|
+
require File.dirname(__FILE__) + "/bracket_grammar"
|
3
|
+
require File.dirname(__FILE__) + '/bracket_tokenizer'
|
5
4
|
|
6
5
|
class TestBracketGrammar < Test::Unit::TestCase
|
7
6
|
def test_recognizes_faulty_bracket_configuration_correctly
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/chittagong_tokenizer"
|
2
|
+
require File.dirname(__FILE__) + "/chittagong_evaluator"
|
3
|
+
|
4
|
+
class ChittagongDriver
|
5
|
+
|
6
|
+
ERROR_MARKER = ">>>"
|
7
|
+
|
8
|
+
def parse_error_message unexpected_token, program
|
9
|
+
if unexpected_token.symbol_name == Dhaka::END_SYMBOL_NAME
|
10
|
+
"Unexpected end of file."
|
11
|
+
else
|
12
|
+
"Unexpected token #{unexpected_token.symbol_name}:\n#{program.insert(unexpected_token.input_position, ERROR_MARKER)}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def tokenize_error_message unexpected_char_index, program
|
17
|
+
"Unexpected character #{program[unexpected_char_index].chr}:\n#{program.insert(unexpected_char_index, ERROR_MARKER)}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def evaluation_error_message evaluation_result, program
|
21
|
+
"#{evaluation_result.exception}:\n#{program.insert(evaluation_result.node.tokens[0].input_position, ERROR_MARKER)}"
|
22
|
+
end
|
23
|
+
|
24
|
+
# lipi:run_method
|
25
|
+
def run(program)
|
26
|
+
tokenize_result = ChittagongTokenizer.tokenize(program)
|
27
|
+
if tokenize_result.has_error?
|
28
|
+
return tokenize_error_message(tokenize_result.unexpected_char_index, program)
|
29
|
+
end
|
30
|
+
|
31
|
+
parse_result = ChittagongParser.parse(tokenize_result)
|
32
|
+
if parse_result.has_error?
|
33
|
+
return parse_error_message(parse_result.unexpected_token, program)
|
34
|
+
end
|
35
|
+
|
36
|
+
evaluation_result = ChittagongEvaluator.new([{}], output_stream = []).
|
37
|
+
evaluate(parse_result)
|
38
|
+
if evaluation_result.exception
|
39
|
+
return (output_stream << evaluation_error_message(evaluation_result, program)).
|
40
|
+
join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
return output_stream.join("\n")
|
44
|
+
end
|
45
|
+
# lipi:run_method
|
46
|
+
|
47
|
+
end
|