# # lua.rb - a Lua module of LangScan # # Copyright (C) 2005 Shinichiro Hamaji <hamaji@nii.ac.jp> # All rights reserved. # This is free software with ABSOLUTELY NO WARRANTY. # # You can redistribute it and/or modify it under the terms of # the GNU General Public License version 2. # require 'langscan/_easyscanner' require 'langscan/_pairmatcher' module LangScan module Lua module_function def name "Lua" end def abbrev "lua" end def extnames [".lua"] end Pattern = [ [:comment, '--.*'], [:string, '\\[\\[', '\\]\\]'], [:string, '""'], [:string, '"', '[^\\\\]"'], [:string, "''"], [:string, "'", "[^\\\\]'"], [:floating, '\\d+\\.\\d+(?:[eE]-?\\d+)?'], [:integer, '\\d+'], [:ident, "[a-zA-Z_]\\w*"], [:punct, '[*+-/^=<>(){}\\[\\];:,\\.]'], [:punct, '(?:~=|<=|>=|==|\\.\\.|\\.\\.\\.)'], ] Types = [] Keywords = %w(and break do else elseif end false for function if in local nil not or repeat return then true until while) def parse_token(t, new_tokens) if t.type == :ident t.type = :funcall end last_token = new_tokens.last return if last_token.nil? return unless t.type == :punct and last_token.type == :funcall if t.text == ':=' || t.text == '=' last_token.type = :fundef end end def scan(input, &block) pm = LangScan::PairMatcher.new(3,2,2,2) pm.define_intertoken_fragment :comment, nil pm.define_pair :paren, :punct, "(", :punct, ")" pm.define_pair :brace, :punct, "{", :punct, "}" pm.define_pair :bracket, :punct, "[", :punct, "]" tokens = Array.new scanner = EasyScanner.new(Pattern, Types, Keywords) scanner.scan(input) do |t| tokens << [t.type, t.text, t.lineno, nil, t.byteno, nil, nil, nil] end def tokens.get_token self.shift end pm.parse(tokens, lambda {|f| if f.type == :ident f.type = IdentType[f.text] end yield f }) {|pair| if (pair.pair_type == :paren) fun = pair.around_open(-1) if (fun) if (fun.type == :ident) f = pair.around_open(-2) if (f && f.type == :keyword && f.text == 'function') fun.type = :fundef else fun.type = :funcall end elsif (fun.type == :keyword && fun.text == 'function') f = pair.around_open(-2) if (f && f.type == :punct && f.text == '=') f = pair.around_open(-3) if (f && f.type == :ident) f.type = :fundef end end end end end } end IdentType = Hash.new(:ident) Keywords.each {|k| IdentType[k] = :keyword } LangScan.register(self) end end