diff options
Diffstat (limited to 'etc/todo')
-rw-r--r-- | etc/todo/scanners/yaml.rb | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/etc/todo/scanners/yaml.rb b/etc/todo/scanners/yaml.rb new file mode 100644 index 0000000..53b052d --- /dev/null +++ b/etc/todo/scanners/yaml.rb @@ -0,0 +1,105 @@ +require 'syntax' + +module Syntax + + # A simple implementation of an YAML lexer. It handles most cases. It is + # not a validating lexer. + class YAML < Tokenizer + + # Step through a single iteration of the tokenization process. This will + # yield (potentially) many tokens, and possibly zero tokens. + def step + if bol? + case + when scan(/---(\s*.+)?$/) + start_group :document, matched + when scan(/(\s*)([a-zA-Z][-\w]*)(\s*):/) + start_group :normal, subgroup(1) + start_group :key, subgroup(2) + start_group :normal, subgroup(3) + start_group :punct, ":" + when scan(/(\s*)-/) + start_group :normal, subgroup(1) + start_group :punct, "-" + when scan(/\s*$/) + start_group :normal, matched + when scan(/#.*$/) + start_group :comment, matched + else + append getch + end + else + case + when scan(/[\n\r]+/) + start_group :normal, matched + when scan(/[ \t]+/) + start_group :normal, matched + when scan(/!+(.*?^)?\S+/) + start_group :type, matched + when scan(/&\S+/) + start_group :anchor, matched + when scan(/\*\S+/) + start_group :ref, matched + when scan(/\d\d:\d\d:\d\d/) + start_group :time, matched + when scan(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(\.\d+)? [-+]\d\d:\d\d/) + start_group :date, matched + when scan(/['"]/) + start_group :punct, matched + scan_string matched + when scan(/:\w+/) + start_group :symbol, matched + when scan(/[:]/) + start_group :punct, matched + when scan(/#.*$/) + start_group :comment, matched + when scan(/>-?/) + start_group :punct, matched + start_group :normal, scan(/.*$/) + append getch until eos? || bol? + return if eos? + indent = check(/ */) + start_group :string + loop do + line = check_until(/[\n\r]|\Z/) + break if line.nil? + if line.chomp.length > 0 + this_indent = line.chomp.match( /^\s*/ )[0] + break if this_indent.length < indent.length + end + append scan_until(/[\n\r]|\Z/) + end + else + start_group :normal, scan_until(/(?=$|#)/) + end + end + end + + private + + def scan_string( delim ) + regex = /(?=[#{delim=="'" ? "" : "\\\\"}#{delim}])/ + loop do + text = scan_until( regex ) + if text.nil? + start_group :string, scan_until( /\Z/ ) + break + else + start_group :string, text unless text.empty? + end + + case peek(1) + when "\\" + start_group :expr, scan(/../) + else + start_group :punct, getch + break + end + end + end + + end + + SYNTAX["yaml"] = YAML + +end |