kpeg 0.9.0 → 1.2.0

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/kpeg.gemspec CHANGED
@@ -1,42 +1,42 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # stub: kpeg 1.0.0.20140103162640 ruby lib
2
3
 
3
4
  Gem::Specification.new do |s|
4
5
  s.name = "kpeg"
5
- s.version = "0.8.5.20120306163408"
6
+ s.version = "1.0.0.20140103162640"
6
7
 
7
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Eric Hodel"]
9
- s.cert_chain = ["/Users/drbrain/.gem/gem-public_cert.pem"]
10
- s.date = "2012-03-07"
9
+ s.authors = ["Evan Phoenix"]
10
+ s.date = "2014-01-04"
11
11
  s.description = "KPeg is a simple PEG library for Ruby. It provides an API as well as native\ngrammar to build the grammar.\n\nKPeg strives to provide a simple, powerful API without being too exotic.\n\nKPeg supports direct left recursion of rules via the\n{OMeta memoization}[http://www.vpri.org/pdf/tr2008003_experimenting.pdf] trick."
12
- s.email = ["drbrain@segment7.net"]
12
+ s.email = ["evan@fallingsnow.net"]
13
13
  s.executables = ["kpeg"]
14
- s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
15
- s.files = [".autotest", "Gemfile", "Gemfile.lock", "History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "bin/kpeg", "examples/calculator/calculator.kpeg", "examples/calculator/calculator.rb", "examples/foreign_reference/literals.kpeg", "examples/foreign_reference/matcher.kpeg", "examples/foreign_reference/matcher.rb", "examples/lua_string/driver.rb", "examples/lua_string/lua_string.kpeg", "examples/lua_string/lua_string.kpeg.rb", "examples/phone_number/README.md", "examples/phone_number/phone_number.kpeg", "examples/phone_number/phone_number.rb", "examples/upper/README.md", "examples/upper/upper.kpeg", "examples/upper/upper.rb", "kpeg.gemspec", "lib/kpeg.rb", "lib/kpeg/code_generator.rb", "lib/kpeg/compiled_parser.rb", "lib/kpeg/format.kpeg", "lib/kpeg/format_parser.rb", "lib/kpeg/grammar.rb", "lib/kpeg/grammar_renderer.rb", "lib/kpeg/match.rb", "lib/kpeg/parser.rb", "lib/kpeg/position.rb", "lib/kpeg/string_escape.kpeg", "lib/kpeg/string_escape.rb", "lib/kpeg/version.rb", "test/inputs/comments.kpeg", "test/test_file_parser_roundtrip.rb", "test/test_gen_calc.rb", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_left_recursion.rb", "vim/syntax_kpeg/ftdetect/kpeg.vim", "vim/syntax_kpeg/syntax/kpeg.vim", ".gemtest"]
14
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc", "examples/phone_number/README.md", "examples/upper/README.md"]
15
+ s.files = [".autotest", ".travis.yml", "History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "bin/kpeg", "examples/calculator/calculator.kpeg", "examples/calculator/calculator.rb", "examples/foreign_reference/literals.kpeg", "examples/foreign_reference/matcher.kpeg", "examples/foreign_reference/matcher.rb", "examples/lua_string/driver.rb", "examples/lua_string/lua_string.kpeg", "examples/lua_string/lua_string.kpeg.rb", "examples/phone_number/README.md", "examples/phone_number/phone_number.kpeg", "examples/phone_number/phone_number.rb", "examples/upper/README.md", "examples/upper/upper.kpeg", "examples/upper/upper.rb", "kpeg.gemspec", "lib/hoe/kpeg.rb", "lib/kpeg.rb", "lib/kpeg/code_generator.rb", "lib/kpeg/compiled_parser.rb", "lib/kpeg/format_parser.kpeg", "lib/kpeg/format_parser.rb", "lib/kpeg/grammar.rb", "lib/kpeg/grammar_renderer.rb", "lib/kpeg/match.rb", "lib/kpeg/parser.rb", "lib/kpeg/position.rb", "lib/kpeg/string_escape.kpeg", "lib/kpeg/string_escape.rb", "test/inputs/comments.kpeg", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_format_parser_round_trip.rb", "test/test_kpeg_grammar.rb", "test/test_kpeg_grammar_renderer.rb", "vim/syntax_kpeg/ftdetect/kpeg.vim", "vim/syntax_kpeg/syntax/kpeg.vim", "test/test_kpeg_string_escape.rb", ".gemtest"]
16
16
  s.homepage = "https://github.com/evanphx/kpeg"
17
+ s.licenses = ["MIT"]
17
18
  s.rdoc_options = ["--main", "README.rdoc"]
18
19
  s.require_paths = ["lib"]
19
20
  s.rubyforge_project = "kpeg"
20
- s.rubygems_version = "1.8.12"
21
- s.signing_key = "/Users/drbrain/.gem/gem-private_key.pem"
21
+ s.rubygems_version = "2.1.10"
22
22
  s.summary = "KPeg is a simple PEG library for Ruby"
23
- s.test_files = ["test/test_file_parser_roundtrip.rb", "test/test_gen_calc.rb", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_left_recursion.rb"]
23
+ s.test_files = ["test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_format_parser_round_trip.rb", "test/test_kpeg_grammar.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_kpeg_string_escape.rb"]
24
24
 
25
25
  if s.respond_to? :specification_version then
26
- s.specification_version = 3
26
+ s.specification_version = 4
27
27
 
28
28
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
- s.add_development_dependency(%q<minitest>, ["~> 2.11"])
30
- s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
31
- s.add_development_dependency(%q<hoe>, ["~> 2.15"])
29
+ s.add_development_dependency(%q<minitest>, ["~> 5.2"])
30
+ s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
31
+ s.add_development_dependency(%q<hoe>, ["~> 3.7"])
32
32
  else
33
- s.add_dependency(%q<minitest>, ["~> 2.11"])
34
- s.add_dependency(%q<rdoc>, ["~> 3.10"])
35
- s.add_dependency(%q<hoe>, ["~> 2.15"])
33
+ s.add_dependency(%q<minitest>, ["~> 5.2"])
34
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
35
+ s.add_dependency(%q<hoe>, ["~> 3.7"])
36
36
  end
37
37
  else
38
- s.add_dependency(%q<minitest>, ["~> 2.11"])
39
- s.add_dependency(%q<rdoc>, ["~> 3.10"])
40
- s.add_dependency(%q<hoe>, ["~> 2.15"])
38
+ s.add_dependency(%q<minitest>, ["~> 5.2"])
39
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
40
+ s.add_dependency(%q<hoe>, ["~> 3.7"])
41
41
  end
42
42
  end
data/lib/hoe/kpeg.rb CHANGED
@@ -10,7 +10,7 @@
10
10
  # license:
11
11
  #
12
12
  # Copyright (c) Ryan Davis, seattle.rb
13
- #
13
+ #
14
14
  # Permission is hereby granted, free of charge, to any person obtaining
15
15
  # a copy of this software and associated documentation files (the
16
16
  # "Software"), to deal in the Software without restriction, including
@@ -18,10 +18,10 @@
18
18
  # distribute, sublicense, and/or sell copies of the Software, and to
19
19
  # permit persons to whom the Software is furnished to do so, subject to
20
20
  # the following conditions:
21
- #
21
+ #
22
22
  # The above copyright notice and this permission notice shall be
23
23
  # included in all copies or substantial portions of the Software.
24
- #
24
+ #
25
25
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26
26
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
27
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -55,9 +55,10 @@ module Hoe::Kpeg
55
55
  def initialize_kpeg
56
56
  self.kpeg_tasks = [:multi, :test, :check_manifest]
57
57
 
58
- # -v = verbose
58
+ # -f = overwrite existing file
59
59
  # -s = parser does not require runtime
60
- self.kpeg_flags ||= "-s -v"
60
+ # -v = verbose
61
+ self.kpeg_flags ||= "-s -v -f"
61
62
 
62
63
  dependency 'kpeg', '~> 0.9', :development
63
64
  end
@@ -83,18 +83,21 @@ module KPeg
83
83
 
84
84
  if output_node
85
85
  code << " end\n"
86
+ code << " module #{root}Construction\n"
86
87
  methods.each do |short, name, attrs|
87
- code << " def #{short}(#{attrs.join(', ')})\n"
88
- code << " #{root}::#{name}.new(#{attrs.join(', ')})\n"
89
- code << " end\n"
88
+ code << " def #{short}(#{attrs.join(', ')})\n"
89
+ code << " #{root}::#{name}.new(#{attrs.join(', ')})\n"
90
+ code << " end\n"
90
91
  end
92
+ code << " end\n"
93
+ code << " include #{root}Construction\n"
91
94
  end
92
95
  end
93
-
96
+
94
97
  def indentify(code, indent)
95
98
  "#{" " * indent}#{code}"
96
99
  end
97
-
100
+
98
101
  # Default indent is 4 spaces (indent=2)
99
102
  def output_op(code, op, indent=2)
100
103
  case op
@@ -109,7 +112,7 @@ module KPeg
109
112
  # Let default ruby string handling figure it out
110
113
  lang = ""
111
114
  end
112
- code << indentify("_tmp = scan(/\\A#{op.regexp}/#{lang})\n", indent)
115
+ code << indentify("_tmp = scan(/\\G#{op.regexp}/#{lang})\n", indent)
113
116
  when CharRange
114
117
  ss = save()
115
118
  if op.start.bytesize == 1 and op.fin.bytesize == 1
@@ -124,7 +127,7 @@ module KPeg
124
127
  left = op.start[0]
125
128
  right = op.fin[0]
126
129
  end
127
-
130
+
128
131
  code << indentify(" unless _tmp >= #{left} and _tmp <= #{right}\n", indent)
129
132
  code << indentify(" self.pos = #{ss}\n", indent)
130
133
  code << indentify(" _tmp = nil\n", indent)
@@ -140,7 +143,7 @@ module KPeg
140
143
  code << indentify("while true # choice\n", indent)
141
144
  op.ops.each_with_index do |n,idx|
142
145
  output_op code, n, (indent+1)
143
-
146
+
144
147
  code << indentify(" break if _tmp\n", indent)
145
148
  code << indentify(" self.pos = #{ss}\n", indent)
146
149
  if idx == op.ops.size - 1
@@ -309,15 +312,23 @@ module KPeg
309
312
  else
310
313
  raise "Unknown op - #{op.class}"
311
314
  end
312
-
313
315
  end
314
316
 
315
- def standalone_region(path)
316
- cp = File.read(path)
317
- start = cp.index("# STANDALONE START")
318
- fin = cp.index("# STANDALONE END")
317
+ def standalone_region(path, marker = "STANDALONE")
318
+ expanded_path = File.expand_path("../#{path}", __FILE__)
319
+ cp = File.read(expanded_path)
320
+
321
+ start_marker = "# #{marker} START"
322
+ end_marker = /^\s*# #{Regexp.escape marker} END/
323
+
324
+ start = cp.index(start_marker) + start_marker.length + 1 # \n
325
+ fin = cp.index(end_marker)
326
+
327
+ unless start and fin
328
+ abort("#{marker} boundaries in #{path} missing " \
329
+ "for standalone generation")
330
+ end
319
331
 
320
- return nil unless start and fin
321
332
  cp[start..fin]
322
333
  end
323
334
 
@@ -326,37 +337,29 @@ module KPeg
326
337
 
327
338
  code = []
328
339
 
329
- if header = @grammar.directives['header']
330
- code << header.action.strip
331
- code << "\n"
332
- end
340
+ output_header(code)
341
+ output_grammar(code)
342
+ output_footer(code)
333
343
 
334
- if @standalone
335
- code << "class #{@name}\n"
336
-
337
- unless cp = standalone_region(
338
- File.expand_path("../compiled_parser.rb", __FILE__))
344
+ @output = code.join
345
+ end
339
346
 
340
- puts "Standalone failure. Check compiler_parser.rb for proper boundary comments"
341
- exit 1
342
- end
347
+ ##
348
+ # Output of class end and footer
343
349
 
344
- unless pp = standalone_region(
345
- File.expand_path("../position.rb", __FILE__))
346
- puts "Standalone failure. Check position.rb for proper boundary comments"
347
- end
350
+ def output_footer(code)
351
+ code << "end\n"
348
352
 
349
- cp.gsub!(/include Position/, pp)
350
- code << cp << "\n"
351
- else
352
- code << "require 'kpeg/compiled_parser'\n\n"
353
- code << "class #{@name} < KPeg::CompiledParser\n"
353
+ if footer = @grammar.directives['footer']
354
+ code << footer.action
354
355
  end
356
+ end
355
357
 
356
- @grammar.setup_actions.each do |act|
357
- code << "\n#{act.action}\n\n"
358
- end
358
+ ##
359
+ # Output of grammar and rules
359
360
 
361
+ def output_grammar(code)
362
+ code << " # :stopdoc:\n"
360
363
  handle_ast(code)
361
364
 
362
365
  fg = @grammar.foreign_grammars
@@ -418,24 +421,57 @@ module KPeg
418
421
 
419
422
  code << "\n Rules = {}\n"
420
423
  @grammar.rule_order.each do |name|
421
- rule = @grammar.rules[name]
422
-
423
424
  rend = GrammarRenderer.escape renderings[name], true
424
425
  code << " Rules[:#{method_name name}] = rule_info(\"#{name}\", \"#{rend}\")\n"
425
426
  end
426
427
 
427
- code << "end\n"
428
+ code << " # :startdoc:\n"
429
+ end
428
430
 
429
- if footer = @grammar.directives['footer']
430
- code << footer.action
431
+ ##
432
+ # Output up to the user-defined setup actions
433
+
434
+ def output_header(code)
435
+ if header = @grammar.directives['header']
436
+ code << header.action.strip
437
+ code << "\n"
431
438
  end
432
439
 
433
- @output = code.join
440
+ pre_class = @grammar.directives['pre-class']
441
+
442
+ if @standalone
443
+ if pre_class
444
+ code << pre_class.action.strip
445
+ code << "\n"
446
+ end
447
+ code << "class #{@name}\n"
448
+
449
+ cp = standalone_region("compiled_parser.rb")
450
+ cpi = standalone_region("compiled_parser.rb", "INITIALIZE")
451
+ pp = standalone_region("position.rb")
452
+
453
+ cp.gsub!(/^\s*include Position/, pp)
454
+ code << " # :stopdoc:\n"
455
+ code << cpi << "\n" unless @grammar.variables['custom_initialize']
456
+ code << cp << "\n"
457
+ code << " # :startdoc:\n"
458
+ else
459
+ code << "require 'kpeg/compiled_parser'\n\n"
460
+ if pre_class
461
+ code << pre_class.action.strip
462
+ code << "\n"
463
+ end
464
+ code << "class #{@name} < KPeg::CompiledParser\n"
465
+ end
466
+
467
+ @grammar.setup_actions.each do |act|
468
+ code << "\n#{act.action}\n\n"
469
+ end
434
470
  end
435
471
 
436
472
  def make(str)
437
473
  m = Module.new
438
- m.module_eval output
474
+ m.module_eval output, "(kpeg parser #{@name})"
439
475
 
440
476
  cls = m.const_get(@name)
441
477
  cls.new(str)
@@ -10,27 +10,33 @@ module KPeg
10
10
 
11
11
  # Leave these markers in! They allow us to generate standalone
12
12
  # code automatically!
13
- #
13
+
14
+ # INITIALIZE START
15
+
16
+ # This is distinct from setup_parser so that a standalone parser
17
+ # can redefine #initialize and still have access to the proper
18
+ # parser setup code.
19
+ def initialize(str, debug=false)
20
+ setup_parser(str, debug)
21
+ end
22
+
23
+ # INITIALIZE END
24
+
14
25
  # STANDALONE START
26
+
27
+ # Prepares for parsing +str+. If you define a custom initialize you must
28
+ # call this method before #parse
15
29
  def setup_parser(str, debug=false)
16
- @string = str
17
- @pos = 0
30
+ set_string str, 0
18
31
  @memoizations = Hash.new { |h,k| h[k] = {} }
19
32
  @result = nil
20
33
  @failed_rule = nil
21
34
  @failing_rule_offset = -1
35
+ @line_offsets = nil
22
36
 
23
37
  setup_foreign_grammar
24
38
  end
25
39
 
26
- # This is distinct from setup_parser so that a standalone parser
27
- # can redefine #initialize and still have access to the proper
28
- # parser setup code.
29
- #
30
- def initialize(str, debug=false)
31
- setup_parser(str, debug)
32
- end
33
-
34
40
  attr_reader :string
35
41
  attr_reader :failing_rule_offset
36
42
  attr_accessor :result, :pos
@@ -41,6 +47,13 @@ module KPeg
41
47
  @string[start..@pos-1]
42
48
  end
43
49
 
50
+ # Sets the string and current parsing position for the parser.
51
+ def set_string string, pos
52
+ @string = string
53
+ @string_size = string ? string.size : 0
54
+ @pos = pos
55
+ end
56
+
44
57
  def show_pos
45
58
  width = 10
46
59
  if @pos < width
@@ -138,28 +151,27 @@ module KPeg
138
151
  end
139
152
 
140
153
  def scan(reg)
141
- if m = reg.match(@string[@pos..-1])
142
- width = m.end(0)
143
- @pos += width
154
+ if m = reg.match(@string, @pos)
155
+ @pos = m.end(0)
144
156
  return true
145
157
  end
146
158
 
147
159
  return nil
148
160
  end
149
161
 
150
- if "".respond_to? :getbyte
162
+ if "".respond_to? :ord
151
163
  def get_byte
152
- if @pos >= @string.size
164
+ if @pos >= @string_size
153
165
  return nil
154
166
  end
155
167
 
156
- s = @string.getbyte @pos
168
+ s = @string[@pos].ord
157
169
  @pos += 1
158
170
  s
159
171
  end
160
172
  else
161
173
  def get_byte
162
- if @pos >= @string.size
174
+ if @pos >= @string_size
163
175
  return nil
164
176
  end
165
177
 
@@ -208,8 +220,7 @@ module KPeg
208
220
  old_pos = @pos
209
221
  old_string = @string
210
222
 
211
- @pos = other.pos
212
- @string = other.string
223
+ set_string other.string, other.pos
213
224
 
214
225
  begin
215
226
  if val = __send__(rule, *args)
@@ -220,15 +231,13 @@ module KPeg
220
231
  end
221
232
  val
222
233
  ensure
223
- @pos = old_pos
224
- @string = old_string
234
+ set_string old_string, old_pos
225
235
  end
226
236
  end
227
237
 
228
238
  def apply_with_args(rule, *args)
229
239
  memo_key = [rule, args]
230
240
  if m = @memoizations[memo_key][@pos]
231
- prev = @pos
232
241
  @pos = m.pos
233
242
  if !m.set
234
243
  m.left_rec = true
@@ -256,14 +265,11 @@ module KPeg
256
265
  else
257
266
  return ans
258
267
  end
259
-
260
- return ans
261
268
  end
262
269
  end
263
270
 
264
271
  def apply(rule)
265
272
  if m = @memoizations[rule][@pos]
266
- prev = @pos
267
273
  @pos = m.pos
268
274
  if !m.set
269
275
  m.left_rec = true
@@ -291,8 +297,6 @@ module KPeg
291
297
  else
292
298
  return ans
293
299
  end
294
-
295
- return ans
296
300
  end
297
301
  end
298
302
 
@@ -1,14 +1,25 @@
1
1
  %% name = KPeg::FormatParser
2
+ %% custom_initialize = true
3
+
4
+ %% pre-class {
5
+ require 'kpeg/grammar'
6
+ }
2
7
 
3
8
  %% {
4
- require 'kpeg/grammar'
9
+
10
+ ##
11
+ # Creates a new kpeg format parser for +str+.
5
12
 
6
13
  def initialize(str, debug=false)
7
14
  setup_parser(str, debug)
8
15
  @g = KPeg::Grammar.new
9
16
  end
10
17
 
18
+ ##
19
+ # The parsed grammar
20
+
11
21
  attr_reader :g
22
+
12
23
  alias_method :grammar, :g
13
24
  }
14
25
 
@@ -22,8 +33,8 @@
22
33
  kleene = "*"
23
34
 
24
35
  # Allow - by itself, but not at the beginning
25
- var = < "-" | /[a-zA-Z][\-_a-zA-Z0-9]*/ > { text }
26
- method = < /[a-zA-Z_][a-zA-Z0-9_]*/ > { text }
36
+ var = < "-" | /[a-z][\w-]*/i > { text }
37
+ method = < /[a-z_]\w*/i > { text }
27
38
 
28
39
  dbl_escapes = "n" { "\n" }
29
40
  | "s" { " " }
@@ -39,7 +50,8 @@
39
50
  | num_escapes
40
51
  | < . > { text }
41
52
  num_escapes = < /[0-7]{1,3}/ > { [text.to_i(8)].pack("U") }
42
- | "x" < /[0-9a-fA-F]{2}/ > { [text.to_i(16)].pack("U") }
53
+ | "x" < /[a-f\d]{2}/i > { [text.to_i(16)].pack("U") }
54
+ # TODO use /\h{2}/ after 1.8 support is dropped
43
55
  dbl_seq = < /[^\\"]+/ > { text }
44
56
  dbl_not_quote = ("\\" dbl_escapes:s | dbl_seq:s)*:ary { Array(ary) }
45
57
  dbl_string = "\"" dbl_not_quote:s "\"" { @g.str(s.join) }
@@ -55,17 +67,17 @@ sgl_escape_quote = "\\'" { "'" }
55
67
  regexp = "/" not_slash:body "/" regexp_opts:opts
56
68
  { @g.reg body, opts }
57
69
 
58
- char = < /[a-zA-Z0-9]/ > { text }
70
+ char = < /[a-z\d]/i > { text }
59
71
  char_range = "[" char:l "-" char:r "]" { @g.range(l,r) }
60
72
 
61
- range_num = < /[1-9][0-9]*/ > { text }
73
+ range_num = < /[1-9]\d*/ > { text }
62
74
  range_elem = < range_num|kleene > { text }
63
75
  mult_range = "[" - range_elem:l - "," - range_elem:r - "]"
64
76
  { [l == "*" ? nil : l.to_i, r == "*" ? nil : r.to_i] }
65
77
  | "[" - range_num:e - "]" { [e.to_i, e.to_i] }
66
78
 
67
79
  curly_block = curly
68
- curly = "{" < (/[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
80
+ curly = "{" < (spaces | /[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
69
81
  nested_paren = "(" (/[^()"']+/ | string | nested_paren)* ")"
70
82
 
71
83
  value = value:v ":" var:n { @g.t(v,n) }
@@ -105,7 +117,7 @@ sgl_escape_quote = "\\'" { "'" }
105
117
  | - var:n - { [n] }
106
118
  statement = - var:v "(" args:a ")" - "=" - expression:o { @g.set(v, o, a) }
107
119
  | - var:v - "=" - expression:o { @g.set(v, o) }
108
- | - "%" var:name - "=" - < /[::A-Za-z0-9_]+/ >
120
+ | - "%" var:name - "=" - < /[:\w]+/ >
109
121
  { @g.add_foreign_grammar(name, text) }
110
122
  | - "%%" - curly:act { @g.add_setup act }
111
123
  | - "%%" - var:name - curly:act { @g.add_directive name, act }
@@ -117,8 +129,8 @@ sgl_escape_quote = "\\'" { "'" }
117
129
 
118
130
  # These are a seperate set of rules used to parse an ast declaration
119
131
 
120
- ast_constant = < /[A-Z][A-Za-z0-9_]*/ > { text }
121
- ast_word = < /[A-Za-z_][A-Za-z0-9_]*/ > { text }
132
+ ast_constant = < /[A-Z]\w*/ > { text }
133
+ ast_word = < /[a-z_]\w*/i > { text }
122
134
 
123
135
  ast_sp = (" " | "\t")*
124
136