Created
July 16, 2016 16:24
-
-
Save JoeRobich/c787e8cbc265bbf5c0e1362e948292d8 to your computer and use it in GitHub Desktop.
Attempt at a MXML Lexer for the rouge ruby gem.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- # | |
module Rouge | |
module Lexers | |
class MXML < ActionScript | |
title "MXML" | |
desc "MXML" | |
tag 'mxml' | |
filenames '*.mxml' | |
mimetypes 'application/xv+xml' | |
def self.analyze_text(text) | |
return 0.9 if text.doctype? | |
return 0.8 if text =~ /\A<\?xml\b/ | |
start = text[0..1000] | |
return 0.6 if start =~ %r(<xml\b) | |
return 0.3 if start =~ %r(<.+?>.*?</.+?>)m | |
end | |
state :root do | |
rule /[^<&]+/, Text | |
rule /&\S*?;/, Name::Entity | |
rule /<!\[CDATA\[/, Comment::Preproc, :actionscript_root | |
rule /<!--/, Comment, :comment | |
rule /<\?.*?\?>/, Comment::Preproc | |
rule /<![^>]*>/, Comment::Preproc | |
# open tags | |
rule %r(<\s*[\w:.-]+)m, Name::Tag, :tag | |
# self-closing tags | |
rule %r(<\s*/\s*[\w:.-]+\s*>)m, Name::Tag | |
end | |
state :comment do | |
rule /[^-]+/m, Comment | |
rule /-->/, Comment, :pop! | |
rule /-/, Comment | |
end | |
state :tag do | |
rule /\s+/m, Text | |
rule /[\w.:-]+\s*=/m, Name::Attribute, :attr | |
rule %r(/?\s*>), Name::Tag, :pop! | |
end | |
state :attr do | |
rule /\s+/m, Text | |
rule /".*?"|'.*?'|[^\s>]+/, Str, :pop! | |
end | |
state :actionscript_root do | |
rule /\]\]\>/, Comment::Preproc, :pop! | |
rule /\A\s*#!.*?\n/m, Comment::Preproc, :actionscript_statement | |
rule /\n/, Text, :actionscript_statement | |
rule %r((?<=\n)(?=\s|/|<!--)), Text, :actionscript_expr_start | |
mixin :actionscript_comments_and_whitespace | |
rule %r(\+\+ | -- | ~ | && | \|\| | \\(?=\n) | << | >>>? | === | |
| !== )x, | |
Operator, :actionscript_expr_start | |
rule %r([:-<>+*%&|\^/!=]=?), Operator, :actionscript_expr_start | |
rule /[(\[,]/, Punctuation, :actionscript_expr_start | |
rule /;/, Punctuation, :actionscript_statement | |
rule /[)\].]/, Punctuation | |
rule /[?]/ do | |
token Punctuation | |
push :actionscript_ternary | |
push :actionscript_expr_start | |
end | |
rule /[{}]/, Punctuation, :actionscript_statement | |
rule id do |m| | |
if self.class.keywords.include? m[0] | |
token Keyword | |
push :actionscript_expr_start | |
elsif self.class.declarations.include? m[0] | |
token Keyword::Declaration | |
push :actionscript_expr_start | |
elsif self.class.reserved.include? m[0] | |
token Keyword::Reserved | |
elsif self.class.constants.include? m[0] | |
token Keyword::Constant | |
elsif self.class.builtins.include? m[0] | |
token Name::Builtin | |
else | |
token Name::Other | |
end | |
end | |
rule /\-[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?/, Num::Float | |
rule /0x[0-9a-fA-F]+/, Num::Hex | |
rule /\-[0-9]+/, Num::Integer | |
rule /"(\\\\|\\"|[^"])*"/, Str::Double | |
rule /'(\\\\|\\'|[^'])*'/, Str::Single | |
end | |
state :actionscript_comments_and_whitespace do | |
rule /\s+/, Text | |
rule %r(//.*?$), Comment::Single | |
rule %r(/\*.*?\*/)m, Comment::Multiline | |
end | |
state :actionscript_expr_start do | |
mixin :actionscript_comments_and_whitespace | |
rule %r(/) do | |
token Str::Regex | |
goto :actionscript_regex | |
end | |
rule /[{]/, Punctuation, :actionscript_object | |
rule //, Text, :pop! | |
end | |
state :actionscript_regex do | |
rule %r(/) do | |
token Str::Regex | |
goto :actionscript_regex_end | |
end | |
rule %r([^/]\n), Error, :pop! | |
rule /\n/, Error, :pop! | |
rule /\[\^/, Str::Escape, :actionscript_regex_group | |
rule /\[/, Str::Escape, :actionscript_regex_group | |
rule /\\./, Str::Escape | |
rule %r{[(][?][:=<!]}, Str::Escape | |
rule /[{][\d,]+[}]/, Str::Escape | |
rule /[()?]/, Str::Escape | |
rule /./, Str::Regex | |
end | |
state :actionscript_regex_end do | |
rule /[gim]+/, Str::Regex, :pop! | |
rule(//) { pop! } | |
end | |
state :actionscript_regex_group do | |
# specially highlight / in a group to indicate that it doesn't | |
# close the regex | |
rule /\//, Str::Escape | |
rule %r([^/]\n) do | |
token Error | |
pop! 2 | |
end | |
rule /\]/, Str::Escape, :pop! | |
rule /\\./, Str::Escape | |
rule /./, Str::Regex | |
end | |
state :actionscript_bad_regex do | |
rule /[^\n]+/, Error, :pop! | |
end | |
def self.keywords | |
@keywords ||= Set.new %w( | |
for in while do break return continue switch case default | |
if else throw try catch finally new delete typeof is | |
this with | |
) | |
end | |
def self.declarations | |
@declarations ||= Set.new %w(var with function) | |
end | |
def self.reserved | |
@reserved ||= Set.new %w( | |
dynamic final internal native public protected private class const | |
override static package interface extends implements namespace | |
set get import include super flash_proxy object_proxy trace | |
) | |
end | |
def self.constants | |
@constants ||= Set.new %w(true false null NaN Infinity undefined) | |
end | |
def self.builtins | |
@builtins ||= %w( | |
void Function Math Class | |
Object RegExp decodeURI | |
decodeURIComponent encodeURI encodeURIComponent | |
eval isFinite isNaN parseFloat parseInt this | |
) | |
end | |
id = /[$a-zA-Z_][a-zA-Z0-9_]*/ | |
# braced parts that aren't object literals | |
state :actionscript_statement do | |
rule /(#{id})(\s*)(:)/ do | |
groups Name::Label, Text, Punctuation | |
end | |
rule /[{}]/, Punctuation | |
mixin :actionscript_expr_start | |
end | |
# object literals | |
state :actionscript_object do | |
mixin :actionscript_comments_and_whitespace | |
rule /[}]/ do | |
token Punctuation | |
goto :actionscript_statement | |
end | |
rule /(#{id})(\s*)(:)/ do | |
groups Name::Attribute, Text, Punctuation | |
push :actionscript_expr_start | |
end | |
rule /:/, Punctuation | |
mixin :actionscript_root | |
end | |
# ternary expressions, where <id>: is not a label! | |
state :actionscript_ternary do | |
rule /:/ do | |
token Punctuation | |
goto :actionscript_expr_start | |
end | |
mixin :actionscript_root | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment