146 lines
5.3 KiB
Ruby
146 lines
5.3 KiB
Ruby
# -*- coding: utf-8 -*- #
|
|
# frozen_string_literal: true
|
|
|
|
module Rouge
|
|
module Lexers
|
|
class ArmAsm < RegexLexer
|
|
title "ArmAsm"
|
|
desc "Arm assembly syntax"
|
|
tag 'armasm'
|
|
filenames '*.s'
|
|
|
|
def self.preproc_keyword
|
|
@preproc_keyword ||= %w(
|
|
define elif else endif error if ifdef ifndef include line pragma undef warning
|
|
)
|
|
end
|
|
|
|
def self.file_directive
|
|
@file_directive ||= %w(
|
|
BIN GET INCBIN INCLUDE LNK
|
|
)
|
|
end
|
|
|
|
def self.general_directive
|
|
@general_directive ||= %w(
|
|
ALIAS ALIGN AOF AOUT AREA ARM ASSERT ATTR CN CODE16 CODE32 COMMON CP
|
|
DATA DCB DCD DCDO DCDU DCFD DCFDU DCFH DCFHU DCFS DCFSU DCI DCI.N DCI.W
|
|
DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT
|
|
EXPORTAS EXTERN FIELD FILL FN FRAME FUNCTION GBLA GBLL GBLS GLOBAL IF
|
|
IMPORT INFO KEEP LCLA LCLL LCLS LEADR LEAF LTORG MACRO MAP MEND MEXIT
|
|
NOFP OPT ORG PRESERVE8 PROC QN RELOC REQUIRE REQUIRE8 RLIST RN ROUT
|
|
SETA SETL SETS SN SPACE STRONG SUBT THUMB THUMBX TTL WEND WHILE
|
|
\[ \] [|!#*=%&^]
|
|
)
|
|
end
|
|
|
|
def self.shift_or_condition
|
|
@shift_or_condition ||= %w(
|
|
ASR LSL LSR ROR RRX AL CC CS EQ GE GT HI HS LE LO LS LT MI NE PL VC VS
|
|
asr lsl lsr ror rrx al cc cs eq ge gt hi hs le lo ls lt mi ne pl vc vs
|
|
)
|
|
end
|
|
|
|
def self.builtin
|
|
@builtin ||= %w(
|
|
ARCHITECTURE AREANAME ARMASM_VERSION CODESIZE COMMANDLINE CONFIG CPU
|
|
ENDIAN FALSE FPIC FPU INPUTFILE INTER LINENUM LINENUMUP LINENUMUPPER
|
|
OBJASM_VERSION OPT PC PCSTOREOFFSET REENTRANT ROPI RWPI TRUE VAR
|
|
)
|
|
end
|
|
|
|
def self.operator
|
|
@operator ||= %w(
|
|
AND BASE CC CC_ENCODING CHR DEF EOR FATTR FEXEC FLOAD FSIZE INDEX LAND
|
|
LEFT LEN LEOR LNOT LOR LOWERCASE MOD NOT OR RCONST REVERSE_CC RIGHT ROL
|
|
ROR SHL SHR STR TARGET_ARCH_[0-9A-Z_]+ TARGET_FEATURE_[0-9A-Z_]+
|
|
TARGET_FPU_[A-Z_] TARGET_PROFILE_[ARM] UAL UPPERCASE
|
|
)
|
|
end
|
|
|
|
state :root do
|
|
rule %r/\n/, Text
|
|
rule %r/^([ \t]*)(#[ \t]*(?:(?:#{ArmAsm.preproc_keyword.join('|')})(?:[ \t].*)?)?)(\n)/ do
|
|
groups Text, Comment::Preproc, Text
|
|
end
|
|
rule %r/[ \t]+/, Text, :command
|
|
rule %r/;.*/, Comment
|
|
rule %r/\$[a-z_]\w*\.?/i, Name::Namespace # variable substitution or macro argument
|
|
rule %r/\w+|\|[^|\n]+\|/, Name::Label
|
|
end
|
|
|
|
state :command do
|
|
rule %r/\n/, Text, :pop!
|
|
rule %r/[ \t]+/ do |m|
|
|
token Text
|
|
goto :args
|
|
end
|
|
rule %r/;.*/, Comment, :pop!
|
|
rule %r/(?:#{ArmAsm.file_directive.join('|')})\b/ do |m|
|
|
token Keyword
|
|
goto :filespec
|
|
end
|
|
rule %r/(?:#{ArmAsm.general_directive.join('|')})(?=[; \t\n])/, Keyword
|
|
rule %r/(?:[A-Z][\dA-Z]*|[a-z][\da-z]*)(?:\.[NWnw])?(?:\.[DFIPSUdfipsu]?(?:8|16|32|64)?){,3}\b/, Name::Builtin # rather than attempt to list all opcodes, rely on all-uppercase or all-lowercase rule
|
|
rule %r/[a-z_]\w*|\|[^|\n]+\|/i, Name::Function # probably a macro name
|
|
rule %r/\$[a-z]\w*\.?/i, Name::Namespace
|
|
end
|
|
|
|
state :args do
|
|
rule %r/\n/, Text, :pop!
|
|
rule %r/[ \t]+/, Text
|
|
rule %r/;.*/, Comment, :pop!
|
|
rule %r/(?:#{ArmAsm.shift_or_condition.join('|')})\b/, Name::Builtin
|
|
rule %r/[a-z_]\w*|\|[^|\n]+\|/i, Name::Variable # various types of symbol
|
|
rule %r/%[bf]?[at]?\d+(?:[a-z_]\w*)?/i, Name::Label
|
|
rule %r/(?:&|0x)\h+(?!p)/i, Literal::Number::Hex
|
|
rule %r/(?:&|0x)[.\h]+(?:p[-+]?\d+)?/i, Literal::Number::Float
|
|
rule %r/0f_\h{8}|0d_\h{16}/i, Literal::Number::Float
|
|
rule %r/(?:2_[01]+|3_[0-2]+|4_[0-3]+|5_[0-4]+|6_[0-5]+|7_[0-6]+|8_[0-7]+|9_[0-8]+|\d+)(?!e)/i, Literal::Number::Integer
|
|
rule %r/(?:2_[.01]+|3_[.0-2]+|4_[.0-3]+|5_[.0-4]+|6_[.0-5]+|7_[.0-6]+|8_[.0-7]+|9_[.0-8]+|[.\d]+)(?:e[-+]?\d+)?/i, Literal::Number::Float
|
|
rule %r/[@:](?=[ \t]*(?:8|16|32|64|128|256)[^\d])/, Operator
|
|
rule %r/[.@]|\{(?:#{ArmAsm.builtin.join('|')})\}/, Name::Constant
|
|
rule %r/[-!#%&()*+,\/<=>?^{|}]|\[|\]|!=|&&|\/=|<<|<=|<>|==|><|>=|>>|\|\||:(?:#{ArmAsm.operator.join('|')}):/, Operator
|
|
rule %r/\$[a-z]\w*\.?/i, Name::Namespace
|
|
rule %r/'/ do |m|
|
|
token Literal::String::Char
|
|
goto :singlequoted
|
|
end
|
|
rule %r/"/ do |m|
|
|
token Literal::String::Double
|
|
goto :doublequoted
|
|
end
|
|
end
|
|
|
|
state :singlequoted do
|
|
rule %r/\n/, Text, :pop!
|
|
rule %r/\$\$/, Literal::String::Char
|
|
rule %r/\$[a-z]\w*\.?/i, Name::Namespace
|
|
rule %r/'/ do |m|
|
|
token Literal::String::Char
|
|
goto :args
|
|
end
|
|
rule %r/[^$'\n]+/, Literal::String::Char
|
|
end
|
|
|
|
state :doublequoted do
|
|
rule %r/\n/, Text, :pop!
|
|
rule %r/\$\$/, Literal::String::Double
|
|
rule %r/\$[a-z]\w*\.?/i, Name::Namespace
|
|
rule %r/"/ do |m|
|
|
token Literal::String::Double
|
|
goto :args
|
|
end
|
|
rule %r/[^$"\n]+/, Literal::String::Double
|
|
end
|
|
|
|
state :filespec do
|
|
rule %r/\n/, Text, :pop!
|
|
rule %r/\$\$/, Literal::String::Other
|
|
rule %r/\$[a-z]\w*\.?/i, Name::Namespace
|
|
rule %r/[^$\n]+/, Literal::String::Other
|
|
end
|
|
end
|
|
end
|
|
end
|