pmacs3/mode/forth.py

133 lines
6.5 KiB
Python
Raw Permalink Normal View History

2009-03-11 15:08:26 -04:00
import time
import tab
2009-03-10 17:12:24 -04:00
from mode import Fundamental
from lex import Grammar, PatternRule, RegionRule, NocasePatternRule
from lex import NocaseRegionRule, NocasePatternMatchRule
2009-03-10 22:58:22 -04:00
from mode.python import StringGrammar2
2009-03-11 23:53:56 -04:00
from mode.pipe import Pipe
2009-03-11 15:08:26 -04:00
from method.shell import Interact
2009-03-10 17:12:24 -04:00
2009-04-11 14:44:05 -04:00
class CodeGrammar(Grammar):
rules = [
PatternRule('word', r'[^ ]+'),
PatternRule('spaces', r' +'),
PatternRule('eol', r' +'),
]
class DataGrammar(Grammar): rules = [PatternRule('data', r'[^)]+')]
class LineGrammar(Grammar): rules = [PatternRule('data', r'.+')]
class StringGrammar3(Grammar): rules = [PatternRule('data', r'[^)]+')]
2009-03-10 22:58:22 -04:00
2009-03-10 17:12:24 -04:00
class ForthGrammar(Grammar):
rules = [
PatternRule('comment', r"\\(?: .*)?\n$"),
RegionRule('comment', r'\((?= |\n|$)', DataGrammar, r'\)'),
NocaseRegionRule('comment', r'0 \[if\]', DataGrammar, r'\[(?:endif|then)\]'),
RegionRule('string', r'[.cs]" ', StringGrammar2, r'"'),
RegionRule('string', r'[.s]\\" ', StringGrammar2, r'"'),
RegionRule('string', r'\.\( ', StringGrammar3, r'\)'),
2009-03-11 23:53:56 -04:00
# builtin
NocasePatternRule('builtin', r'(?:true|false|on|off)(?= |\n|$)'),
2009-03-11 23:53:56 -04:00
# mathn
NocasePatternRule('keyword', 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|$)'),
2009-03-11 23:53:56 -04:00
# stack
NocasePatternRule('keyword', 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|$)'),
2009-03-11 23:53:56 -04:00
# pointer
NocasePatternRule('keyword', r'(?:forthsp|sp@|sp!|fp@|fp!|rp@|rp!|lp@|lp!)(?= |\n|$)'),
2009-03-11 23:53:56 -04:00
# address
NocasePatternRule('keyword', 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('builtin', 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('builtin', 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|$)'),
2009-03-11 23:53:56 -04:00
# define
NocasePatternRule('builtin', 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 (*)
2009-04-11 14:44:05 -04:00
NocaseRegionRule('code', 'code', CodeGrammar, 'end-code'),
NocasePatternRule('builtin', r'(?:assembler|code|end-code|;code|flush-icache|c,)(?= |\n|$)'),
2009-03-11 23:53:56 -04:00
# xyz
NocasePatternMatchRule('x', r'(:)( +)([^ ]+)', r'delimiter', r'spaces', r'function'),
PatternRule('delimiter', r"[:;\[\]]"),
NocasePatternRule('number', r"'[a-z](?= |$)"),
NocasePatternRule('number', r'%?-?[0-1]+\.?(?= |$)'),
NocasePatternRule('number', r'[&#]?-?[0-9]+\.?(?= |$)'),
NocasePatternRule('number', r"(?:0x|\$)[0-9a-f]+\.?(?= |$)"),
NocasePatternRule('number', r'[+-]?[0-9]+\.?e?[+-][0-9]+(?= |$)'),
2009-04-11 14:44:05 -04:00
PatternRule('forth.word', r'[^ ]+'),
PatternRule('spaces', r' +'),
PatternRule('eol', r'\n'),
2009-03-10 17:12:24 -04:00
]
2009-03-11 15:08:26 -04:00
class GforthStart(Interact):
args = []
2009-03-11 23:53:56 -04:00
modename = 'forthpipe'
2009-04-07 00:34:26 -04:00
reuse = True
2009-03-11 15:08:26 -04:00
def _execute(self, w, **vargs):
Interact._execute(self, w, bname='*GForth*', cmd='gforth')
class GforthLoadFile(Interact):
args = []
2009-03-11 23:53:56 -04:00
modename = 'forthpipe'
2009-04-07 00:34:26 -04:00
reuse = True
2009-03-11 15:08:26 -04:00
def _execute(self, w, **vargs):
Interact._execute(self, w, bname='*GForth*', cmd='gforth')
b = w.application.get_buffer_by_name('*GForth*')
2009-03-11 23:53:56 -04:00
time.sleep(2.0)
2009-03-11 20:36:15 -04:00
path = w.buffer.path
b.pipe_write('s" ' + path + '" included\n')
2009-03-11 15:08:26 -04:00
br = RegionRule('banner', r'^Gforth \d+\.\d+\.\d+', LineGrammar, r"^Type `bye' to exit\n$")
2009-03-11 23:53:56 -04:00
class ForthPipeGrammar(Grammar):
rules = [br] + ForthGrammar.rules
2009-03-11 23:53:56 -04:00
class ForthPipe(Pipe):
2009-03-18 10:10:10 -04:00
name = 'forthpipe'
grammar = ForthPipeGrammar
2009-03-11 23:53:56 -04:00
dopen = {}
for s in ['if', 'case', 'of', '?dup-if', '?dup-0=-if', 'begin', 'while',
'until', '?do', 'for', 'code']:
dopen[s] = None
dclose = {}
for s in ['then', 'endif', 'again']:
dclose[s] = None
class ForthTabber(tab.StackTabber2):
open_tokens = {'builtin': dopen, 'delimiter': {':': ';'}}
close_tokens = {'builtin': dclose, 'delimiter': set([';'])}
continue_tokens = {'nomatch': set()}
fixed_indent = True
def is_base(self, y):
return y == 0
def _is_indent(self, t):
return t.name == 'spaces'
def _is_ignored(self, t):
return t.fqname() in ('spaces', 'eol', 'comment', 'comment.start',
'comment.data', 'comment.null', 'comment.end')
def _handle_other_token(self, y, tokens, start, end, i, t):
tab.StackTabber2._handle_other_token(self, y, tokens, start, end, i, t)
if t.match('builtin', 'else'):
if len(self.stack) > 1:
self.curr_level = self.stack[-2].level
else:
self.curr_level = 0
2009-03-10 17:12:24 -04:00
class Forth(Fundamental):
name = 'FORTH'
2009-03-10 22:58:22 -04:00
extensions = ['.fs', '.fi', '.fb']
2009-03-10 17:12:24 -04:00
grammar = ForthGrammar
commentc = '\\ '
2009-03-11 23:53:56 -04:00
actions = [GforthStart, GforthLoadFile]
tabbercls = ForthTabber
2009-03-10 17:12:24 -04:00
colors = {
2009-04-11 14:44:05 -04:00
'forth.word': ('yellow', 'default', 'bold'),
'forth.code': ('green', 'default', 'bold'),
2009-03-10 17:12:24 -04:00
}
2009-03-11 23:53:56 -04:00
def install(*args):
Forth.install(*args)
ForthPipe.install(*args)