import time import tab from mode import Fundamental from lex import Grammar, PatternRule, RegionRule, NocasePatternRule from lex import NocaseRegionRule, NocasePatternMatchRule from mode.python import StringGrammar2 from mode.pipe import Pipe from method.shell import Interact class DataGrammar(Grammar): rules = [PatternRule('data', r'[^)]+')] class LineGrammar(Grammar): rules = [PatternRule('data', r'.+')] class StringGrammar3(Grammar): rules = [PatternRule('data', r'[^)]+')] 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'\)'), # builtin NocasePatternRule('builtin', r'(?:true|false|on|off)(?= |\n|$)'), # 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|$)'), # 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|$)'), # pointer NocasePatternRule('keyword', r'(?:forthsp|sp@|sp!|fp@|fp!|rp@|rp!|lp@|lp!)(?= |\n|$)'), # 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|$)'), # 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>||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('builtin', r'(?:assembler|code|end-code|;code|flush-icache|c,)(?= |\n|$)'), # 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]+(?= |$)'), PatternRule('forth_word', r'[^ ]+'), PatternRule('spaces', r' +'), PatternRule('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') br = RegionRule('banner', r'^Gforth \d+\.\d+\.\d+', LineGrammar, r"^Type `bye' to exit\n$") class ForthPipeGrammar(Grammar): rules = [br] + ForthGrammar.rules class ForthPipe(Pipe): name = 'forthpipe' grammar = ForthPipeGrammar 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 class Forth(Fundamental): name = 'FORTH' extensions = ['.fs', '.fi', '.fb'] grammar = ForthGrammar commentc = '\\ ' actions = [GforthStart, GforthLoadFile] tabbercls = ForthTabber colors = { 'forth_word': ('yellow', 'default', 'bold'), } def install(*args): Forth.install(*args) ForthPipe.install(*args)