pmacs3/mode/forth.py

107 lines
5.5 KiB
Python

import time
from mode import Fundamental
from lex import Grammar, PatternRule, RegionRule, NocasePatternRule, NocaseRegionRule
from mode.python import StringGrammar2
from mode.pipe import Pipe
from method.shell import Interact
class DataGrammar(Grammar):
rules = [PatternRule(r'data', r'[^)]+')]
class LineGrammar(Grammar):
rules = [PatternRule(r'data', r'.+')]
class StringGrammar3(Grammar):
rules = [PatternRule(r'data', r'[^)]+')]
class ForthGrammar(Grammar):
rules = [
PatternRule(r'comment', r"\\(?: .*)?\n$"),
RegionRule(r'comment', r'\((?= |\n)', DataGrammar, r'\)'),
NocaseRegionRule(r'comment', r'0 \[if\]', DataGrammar, r'\[(?:endif|then)\]'),
PatternRule(r'delimiter', r"[:;\[\]]"),
RegionRule(r'string', r'[.cs]" ', StringGrammar2, r'"'),
RegionRule(r'string', r'[.s]\\" ', StringGrammar2, r'"'),
RegionRule(r'string', r'\.\( ', StringGrammar3, r'\)'),
# builtin
NocasePatternRule(r'forth_builtin', r'(?:true|false|on|off)(?= |\n|$)'),
# math
NocasePatternRule(r'forth_operator', r'(?:\+|-|\*/mod|\*/|\*|/mod|/|mod|negate|abs|min|max|and|or|xor|not|lshift|rshift|invert|2\*|2/|2\+|2-|1\+|1-|8\*|under\+|m\+|m\*/|m\*|um/mod|um\*|fm/mod|sm/rem|d\+|d-|dnegate|dabs|dmin|dmax|d2\*|d2/|f\+|f-|f\*\*|f\*|f/|fnegate|fabs|fmax|fmin|floor|fround|fsqrt|fexpm1|fexp|flnp1|fln|flog|falog|fsincos|fsinh|fsin|fcosh|fcos|ftanh|ftan|fasinh|fasin|facosh|facos|fatan2|fatanh|fatan|f2\*|f2/|1/f|f~rel|f~abs|f~|0<>|0<=|0<|0=|0>=|0>|<>|<=|<|>=|>|=|u<=|u<|u>=|u>|d0<=|d0<>|d0<|d0=|d0>=|d0>|d<=|d<>|d<|d=|d>=|d>|du<=|du<|du>=|du>|within|\?negate|\?dnegate)(?= |\n|$)'),
# stack
NocasePatternRule(r'forth_operator', r'(?:drop|nip|dup|over|tuck|swap|rot|-rot|\?dup|pick|roll|2drop|2nip|2dup|2over|2tuck|2swap|2rot|2-rot|3dup|4dup|5dup|3drop|4drop|5drop|8drop|4swap|4rot|4-rot|4tuck|8swap|8dup|>r|r>|r@|rdrop|2>r|2r>|2r@|2rdrop|4>r|4r>|4r@|4rdrop|fdrop|fnip|fdup|fover|ftuck|fswap|frot)(?= |\n|$)'),
# pointer
NocasePatternRule(r'forth_operator', r'(?:forthsp|sp@|sp!|fp@|fp!|rp@|rp!|lp@|lp!)(?= |\n|$)'),
# address
NocasePatternRule(r'forth_operator', r'(?:@|!|\+!|c@|c!|2@|2!|f@|f!|sf@|sf!|df@|df!|chars|char\+|cells|cell\+|cell|align|aligned|floats|float\+|float|faligned|falign|sfloats|sfloat\+|sfaligned|sfalign|dfloats|dfloat\+|dfaligned|dfalign|maxaligned|maxalign|cfaligned|cfalign|address-unit-bits|allot|allocate|here|move|erase|cmove>|cmove|fill|blank)(?= |\n|$)'),
# conditional
NocasePatternRule(r'forth_keyword', r'(?:if|else|endif|then|case|of|endof|endcase|\?dup-if|\?dup-0=-if|ahead|cs-pick|cs-roll|catch|throw|within)(?= |\n|$)'),
# iter
NocasePatternRule(r'forth_operator', r'(?:begin|while|repeat|until|again|\?do|loop|i|j|k|\+do|u\+do|u-do|-do|do|\+loop|-loop|unloop|leave|\?leave|exit|done|for|next)(?= |\n|$)'),
# define
NocasePatternRule(r'forth_keyword', r'(?:constant|2constant|fconstant|variable|2variable|fvariable|create|user|to|defer|is|does>|immediate|compile-only|compile|restrict|interpret|postpone|execute|literal|create-interpret/compile|interpretation>|<interpretation|compilation>|<compilation|\]|lastxt|comp\'|postpone|find-name|name>int|name\?int|name>comp|name>string|state|c;|cvariable|,|2,|f,|c,|\[(?:ifdef|ifundef|then|endif|then|else|\?do|do|loop|\+loop|next|begin|until|again|while|repeat|comp\'|\'|compile)\])(?= |\n|$)'),
# assembly
NocasePatternRule(r'forth_keyword', r'(?:assembler|code|end-code|;code|flush-icache|c,)(?= |\n|$)'),
# xyz
PatternRule(r'forth_def', r'(?<=:) +[^ ]+'),
NocasePatternRule(r'number', r"'[a-z](?= |$)"),
NocasePatternRule(r'number', r'%?-?[0-1]+\.?(?= |$)'),
NocasePatternRule(r'number', r'[&#]?-?[0-9]+\.?(?= |$)'),
NocasePatternRule(r'number', r"(?:0x|\$)[0-9a-f]+\.?(?= |$)"),
NocasePatternRule(r'number', r'[+-]?[0-9]+\.?e?[+-][0-9]+(?= |$)'),
PatternRule(r'forth_word', r'[^ ]+'),
PatternRule(r'spaces', r' +'),
PatternRule(r'eol', r'\n'),
]
class GforthStart(Interact):
args = []
modename = 'forthpipe'
def _execute(self, w, **vargs):
Interact._execute(self, w, bname='*GForth*', cmd='gforth')
class GforthLoadFile(Interact):
args = []
modename = 'forthpipe'
def _execute(self, w, **vargs):
Interact._execute(self, w, bname='*GForth*', cmd='gforth')
b = w.application.get_buffer_by_name('*GForth*')
time.sleep(2.0)
path = w.buffer.path
b.pipe_write('s" ' + path + '" included\n')
class CodePipeGrammar(Grammar):
rules = [
PatternRule(r'comment', r"\\(?: .*)?\n$"),
PatternRule(r'addr', r'\$[0-9A-F]+'),
PatternRule(r'addr2', r'\[[a-z]+\]'),
]
class ForthPipeGrammar(Grammar):
rules = list(ForthGrammar.rules)
br = RegionRule(r'banner', r'^Gforth \d+\.\d+\.\d+', LineGrammar, r"^Type `bye' to exit\n$")
ForthPipeGrammar.rules.insert(0, br)
class ForthPipe(Pipe):
modename = 'forthpipe'
grammar = ForthPipeGrammar
class Forth(Fundamental):
modename = 'FORTH'
extensions = ['.fs', '.fi', '.fb']
grammar = ForthGrammar
commentc = '\\'
actions = [GforthStart, GforthLoadFile]
colors = {
'forth_def': ('blue', 'default', 'bold'),
'forth_word': ('yellow', 'default', 'bold'),
'forth_keyword': ('magenta', 'default', 'bold'),
'forth_operator': ('cyan', 'default', 'bold'),
'forth_builtin': ('magenta', 'default', 'bold'),
}
def install(*args):
Forth.install(*args)
ForthPipe.install(*args)