pratt_parser 0.0.0 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2be786fcdd7e3a6860fd2218ae404036a6de85e1
4
- data.tar.gz: b0684865ee6fcbb04ef26544819e43598e2dfa3a
3
+ metadata.gz: f8429fe8f5e629ccb6048fdc5766a278bbd5f5ae
4
+ data.tar.gz: 03df74e2cb12a8403dd4025c5a4597d3da067a0f
5
5
  SHA512:
6
- metadata.gz: 6d7a691fa927a0e0095827cf1abebdf4ac8102a12774b6b60a93693eef495beabe79ef4b6f4885d99ccecf5928957684f7eb1fdc377b032300eec099a8943cc9
7
- data.tar.gz: 3d8549f09a0d0b74b45238f390b0124fe5e7cbcaf6e9e25a13513f45701212945044add373e623e8064b005bdb6f2cc313ebfc65dd9700db824b20dec28fcde5
6
+ metadata.gz: b215b84b04fde6efdbce9c5244ece12be8b9cb9d9e268056cd2699eb63e30f253c93e17e8cfd1287de0fc1702514a26c5b3e4154fa11a21712b248e1019685a9
7
+ data.tar.gz: e27d791be91a17b96ca7907f32a53274a6ade2a7ab2d88c6cbbfc3d1c77e05f0fc313c560228a6085af4514cf9072d99303e2a31a5c3e8831e768bdce446d9d8
data/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ ## 0.0.1 ##
2
+
3
+ * Include examples.
4
+
5
+ ## 0.0.0 ##
6
+
7
+ * Initial release.
8
+
data/README.md CHANGED
@@ -1,19 +1,26 @@
1
1
  Pratt Parser
2
2
  ============
3
3
 
4
- A Pratt Parser. Construct it with a Lexer that returns tokens that
5
- define the language to be parsed and combines terms.
4
+ A Pratt Parser. Just a simple parsing framework.
5
+
6
+ Define tokens that describe your language and combine terms. Write a
7
+ Lexer (an Enumerator) that produces a stream of tokens. Instantiate a
8
+ PrattParser and call #eval to parse the stream and return whatever
9
+ your tokens want.
6
10
 
7
11
  Pratt parsers are like recursive descent parsers but instead of having
8
12
  to code a function for each production you just code up some token
9
- objects which define their own prededence and associativity. So it's
10
- simple to add new tokens without having to rewrite a bunch of
11
- recursive descent functions.
13
+ objects which define their own prededence and associativity and how
14
+ subexpressions to the left and/or right are combined. So it's simple
15
+ to add new language features/tokens without having to rewrite a bunch
16
+ of recursive descent functions.
12
17
 
13
18
  Pratt parsers are also more efficient than recursive descent parsers
14
19
  since they don't need to recurse all the way down to the bottom level
15
20
  to figure out what to do.
16
21
 
22
+ Read more:
23
+
17
24
  http://javascript.crockford.com/tdop/tdop.html
18
25
 
19
26
  http://effbot.org/zone/simple-top-down-parsing.htm
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Evaluate simple arithmetic expressions using a PrattParser.
4
+ # Supports +, -, *, /, ^ (with ustomarycorrect precedence and
5
+ # associativity, and parentheses. Also supports = to compare numbers
6
+ # and booleans. Adding support for < and > would be a simple matter
7
+ # of adding some more tokens.
8
+ #
9
+ # Supporting whitespace needs a lexer that throws away whitespace.
10
+ #
11
+ # Numeric integer constants are supported using single-digit tokens
12
+ # which are left-associatiuve.
13
+
14
+ require "pratt_parser"
15
+
16
+ class PrattEvaluator
17
+ def self.eval(expression)
18
+ PrattParser.new(Lexer.new(expression)).eval
19
+ end
20
+
21
+ class Lexer
22
+ # Note that new returns an Enumerator, not a Lexer.
23
+
24
+ def self.new(expression)
25
+ expression.each_char.lazy.map{|c|@@tokens[c]}
26
+ end
27
+
28
+ class Token
29
+ def initialize(lbp)
30
+ @lbp = lbp
31
+ end
32
+
33
+ def lbp
34
+ @lbp
35
+ end
36
+ end
37
+
38
+ class InfixToken < Token
39
+ def initialize(lbp, associates = :left, &block)
40
+ super(lbp)
41
+ @block = block
42
+ @rbp = (associates == :left ? lbp : lbp - 1)
43
+ end
44
+
45
+ def led(parser, left)
46
+ @block.call(left, parser.expression(@rbp))
47
+ end
48
+ end
49
+
50
+ class DigitToken < Token
51
+ def initialize(lbp, value)
52
+ super(lbp)
53
+ @value = value
54
+ end
55
+
56
+ def nud(parser)
57
+ @value
58
+ end
59
+
60
+ def led(parser, left)
61
+ left*10 + @value
62
+ end
63
+ end
64
+
65
+ class LeftParenToken < Token
66
+ def nud(parser)
67
+ parser.expression(lbp).tap do
68
+ parser.expect(RightParenToken)
69
+ end
70
+ end
71
+ end
72
+
73
+ class RightParenToken < Token
74
+ end
75
+
76
+ @@tokens = {}
77
+
78
+ def self.token(char, t)
79
+ @@tokens[char] = t
80
+ end
81
+
82
+ def self.infix(char, lbp, associates = :left, &block)
83
+ token(char, InfixToken.new(lbp, associates, &block))
84
+ end
85
+
86
+ token("(", LeftParenToken.new(0))
87
+ token(")", RightParenToken.new(0))
88
+
89
+ infix("=", 10, &:==)
90
+ infix("+", 20, &:+)
91
+ infix("-", 20, &:-)
92
+ infix("*", 30, &:*)
93
+ infix("/", 30, &:/)
94
+ infix("^", 40, :right, &:**)
95
+
96
+ (0..9).each do |d|
97
+ token(d.to_s, DigitToken.new(100, d.to_f))
98
+ end
99
+ end
100
+ end
101
+
102
+ if __FILE__ == $0
103
+ puts PrattEvaluator.eval(ARGV[0])
104
+ end
data/pratt_parser.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  Gem::Specification.new do |gem|
2
- gem.description = "A Pratt parser. Create token objects to define your language."
2
+ gem.description = "A Pratt parser. Create token objects to define your language. Create a lexer to return tokens. Call the parser to grok the language."
3
3
  gem.summary = "A Pratt parser."
4
4
  gem.authors = ["Tom May"]
5
5
  gem.email = ["tom@tommay.net"]
6
6
  gem.homepage = "https://github.com/tommay/pratt_parser"
7
- gem.files = `git ls-files | egrep -v '^example'`.split("\n")
7
+ gem.files = `git ls-files`.split("\n")
8
8
  gem.test_files = `git ls-files -- spec/*`.split("\n")
9
9
  gem.name = "pratt_parser"
10
10
  gem.require_paths = ["lib"]
11
- gem.version = "0.0.0"
11
+ gem.version = "0.0.1"
12
12
  gem.license = "MIT"
13
13
  # gem.required_ruby_version = '>= 2.1.0'
14
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pratt_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom May
@@ -10,7 +10,8 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2015-02-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A Pratt parser. Create token objects to define your language.
13
+ description: A Pratt parser. Create token objects to define your language. Create
14
+ a lexer to return tokens. Call the parser to grok the language.
14
15
  email:
15
16
  - tom@tommay.net
16
17
  executables: []
@@ -18,9 +19,11 @@ extensions: []
18
19
  extra_rdoc_files: []
19
20
  files:
20
21
  - ".gitignore"
22
+ - CHANGELOG
21
23
  - LICENSE.md
22
24
  - README.md
23
25
  - Rakefile
26
+ - examples/expression_evaluator.rb
24
27
  - lib/pratt_parser.rb
25
28
  - pratt_parser.gemspec
26
29
  homepage: https://github.com/tommay/pratt_parser