- Added more complicated Animation definition expression - Added 0.3d compiler lexer ignores (so it will still parse the 0.3d compatible sections of KLL 0.5) - Improved funcparserlib/parser.py to include next token (if available) on NoParseErrordev
@@ -27,7 +27,7 @@ kll <kll files> | |||
### Kiibohd Controller Usage | |||
```bash | |||
kll.py <misc kll files> --config <config/capability kll files> --base <basemap kll files) --default <default layer kll files> --partial <partial layer 1 kll files> --partial <partial layer 2 kll files> | |||
kll <misc kll files> --config <config/capability kll files> --base <basemap kll files) --default <default layer kll files> --partial <partial layer 1 kll files> --partial <partial layer 2 kll files> | |||
``` | |||
See `kll --help` for the most up to date documentation |
@@ -864,7 +864,7 @@ class OperationSpecificsStage( Stage ): | |||
( 'AnimationStart', ( r'A\[', ) ), | |||
( 'CodeBegin', ( r'\[', ) ), | |||
( 'CodeEnd', ( r'\]', ) ), | |||
( 'Position', ( r'r?[xyz]:[0-9]+(.[0-9]+)?', ) ), | |||
( 'Position', ( r'r?[xyz]:-?[0-9]+(.[0-9]+)?', ) ), | |||
( 'Comma', ( r',', ) ), | |||
( 'Dash', ( r'-', ) ), | |||
@@ -887,7 +887,7 @@ class OperationSpecificsStage( Stage ): | |||
( 'ScanCodeStart', ( r'S\[', ) ), | |||
( 'CodeBegin', ( r'\[', ) ), | |||
( 'CodeEnd', ( r'\]', ) ), | |||
( 'Position', ( r'r?[xyz]:[0-9]+(.[0-9]+)?', ) ), | |||
( 'Position', ( r'r?[xyz]:-?[0-9]+(.[0-9]+)?', ) ), | |||
( 'PixelOperator', ( r'(\+:|-:|>>|<<)', ) ), | |||
( 'String', ( r'"[^"]*"', ) ), | |||
@@ -897,7 +897,7 @@ class OperationSpecificsStage( Stage ): | |||
( 'Dash', ( r'-', ) ), | |||
( 'Plus', ( r'\+', ) ), | |||
( 'Parenthesis', ( r'\(|\)', ) ), | |||
( 'Percent', ( r'0|([1-9][0-9]*)%', ) ), | |||
( 'Percent', ( r'(0|([1-9][0-9]*))%', ) ), | |||
( 'Number', ( r'-?(0x[0-9a-fA-F]+)|(0|([1-9][0-9]*))', ) ), | |||
( 'Name', ( r'[A-Za-z_][A-Za-z_0-9]*', ) ), | |||
] |
@@ -1,6 +1,6 @@ | |||
#!/usr/bin/env python3 | |||
''' | |||
KLL Kiibohd .h File Emitter | |||
KLL Kiibohd .h/.c File Emitter | |||
''' | |||
# Copyright (C) 2016 by Jacob Alexander | |||
@@ -238,10 +238,12 @@ class Kiibohd( Emitter, TextEmitter ): | |||
variables = full_context.query( 'AssignmentExpression', 'Variable' ) | |||
for dkey, dvalue in sorted( defines.data.items() ): | |||
if dvalue.name in variables.data.keys(): | |||
self.fill_dict['Defines'] += "\n#define {0} {1}".format( | |||
dvalue.association, | |||
variables.data[ dvalue.name ].value.replace( '\n', ' \\\n' ), | |||
) | |||
# TODO Handle arrays | |||
if not isinstance( variables.data[ dvalue.name ].value, list ): | |||
self.fill_dict['Defines'] += "\n#define {0} {1}".format( | |||
dvalue.association, | |||
variables.data[ dvalue.name ].value.replace( '\n', ' \\\n' ), | |||
) | |||
else: | |||
print( "{0} '{1}' not defined...".format( WARNING, dvalue.name ) ) | |||
@@ -3,3 +3,7 @@ Array[] = a b c "b c" 3; | |||
Index[5] = "this text" thing; # Single element | |||
Index[6] = moar; | |||
Variable => Variable_define; | |||
Array => Array_define; | |||
Index => Index_define; | |||
@@ -54,6 +54,10 @@ A[BLEEdsing2, 8] <= U"B"(40,50,0x60); | |||
A[BLEEdsing2, 9] <= S120(40,50,0x60); | |||
A[BLEEdsing2, 10] <= S[0x10](40,50,0x60); | |||
A[RainbowFillInterp] <= start, interp:on; | |||
A[RainbowFillInterp, 1] <= P[c:20%](255,255,0), P[c:40%](255,0,0), P[c:60%](127,0,255), P[c:80%](0,0,255); | |||
A[RainbowFillInterp, 2] <= P[c:0%](0,255,0), P[c:20%](255,255,0), P[c:40%](255,0,0), P[c:60%](127,0,255), P[c:80%](0,0,255); | |||
# Animation Triggers | |||
myCapability => myFunc( myArg1 : 1, myArg2 : 4 ); | |||
A[BLEEdsing, 3] : myCapability( 0x8, 0x25 ); |
@@ -151,7 +151,7 @@ class Parser(object): | |||
tok = tokens[max] | |||
else: | |||
tok = '<EOF>' | |||
raise NoParseError('%s: %s' % (e.msg, tok), e.state) | |||
raise NoParseError('%s: %s' % (e.msg, tok), e.state, tok) | |||
def __add__(self, other): | |||
"""Parser(a, b), Parser(a, c) -> Parser(a, _Tuple(b, c)) | |||
@@ -265,9 +265,10 @@ class State(object): | |||
class NoParseError(Exception): | |||
def __init__(self, msg='', state=None): | |||
def __init__(self, msg='', state=None, token=None): | |||
self.msg = msg | |||
self.state = state | |||
self.token = token # Next token | |||
def __str__(self): | |||
return self.msg | |||
@@ -294,7 +295,7 @@ def finished(tokens, s): | |||
if s.pos >= len(tokens): | |||
return None, s | |||
else: | |||
raise NoParseError('should have reached <EOF>', s) | |||
raise NoParseError('should have reached <EOF>', s, tokens[s.pos]) | |||
finished.name = 'finished' | |||
@@ -344,7 +345,7 @@ def some(pred): | |||
else: | |||
if debug: | |||
log.debug('failed "%s", state = %s' % (t, s)) | |||
raise NoParseError('got unexpected token', s) | |||
raise NoParseError('got unexpected token', s, t) | |||
_some.name = '(some)' | |||
return _some |
@@ -149,10 +149,14 @@ def tokenize( string ): | |||
( 'LedCodeStart', ( r'LED\[', ) ), | |||
( 'ScanCode', ( r'S((0x[0-9a-fA-F]+)|([0-9]+))', ) ), | |||
( 'ScanCodeStart', ( r'S\[', ) ), | |||
( 'PixelCodeStart', ( r'P\[.*', ) ), # Discarded, needs KLL 0.5 | |||
( 'AnimationStart', ( r'A\[.*', ) ), # Discarded, needs KLL 0.5 | |||
( 'CodeStart', ( r'\[', ) ), | |||
( 'CodeEnd', ( r'\]', ) ), | |||
( 'String', ( r'"[^"]*"', ) ), | |||
( 'SequenceString', ( r"'[^']*'", ) ), | |||
( 'Operator', ( r'=>|:\+|:-|::|:|=', ) ), | |||
( 'Position', ( r'r?[xyz]:-?[0-9]+(.[0-9]+)?', ) ), | |||
( 'Operator', ( r'<=|=>|:\+|:-|::|:|=', ) ), | |||
( 'Number', ( r'(-[ \t]*)?((0x[0-9a-fA-F]+)|(0|([1-9][0-9]*)))', VERBOSE ) ), | |||
( 'Comma', ( r',', ) ), | |||
( 'Dash', ( r'-', ) ), | |||
@@ -167,6 +171,9 @@ def tokenize( string ): | |||
# Tokens to filter out of the token stream | |||
useless = ['Space', 'Comment'] | |||
# Discarded expresssions (KLL 0.4+) | |||
useless.extend( ['PixelCodeStart', 'AnimationStart'] ) | |||
tokens = make_tokenizer( specs ) | |||
return [x for x in tokens( string ) if x.type not in useless] | |||
@@ -596,6 +603,7 @@ sysCode = tokenType('SysCode') >> make_sysCode | |||
none = tokenType('None') >> make_none | |||
name = tokenType('Name') | |||
number = tokenType('Number') >> make_number | |||
position = tokenType('Position') | |||
comma = tokenType('Comma') | |||
dash = tokenType('Dash') | |||
plus = tokenType('Plus') | |||
@@ -606,7 +614,8 @@ seqString = tokenType('SequenceString') >> make_seqString | |||
unseqString = tokenType('SequenceString') >> make_unseqString # For use with variables | |||
# Code variants | |||
code_end = tokenType('CodeEnd') | |||
code_start = tokenType('CodeStart') | |||
code_end = tokenType('CodeEnd') | |||
# Scan Codes | |||
scanCode_start = tokenType('ScanCodeStart') | |||
@@ -669,7 +678,7 @@ resultCode_outerList = ( ( capFunc_sequence >> optionExpansion ) | none ) >> | |||
#| <variable> = <variable contents>; | |||
variable_contents = name | content | string | number | comma | dash | unseqString | |||
variable_expression = name + skip( operator('=') ) + oneplus( variable_contents ) + skip( eol ) >> set_variable | |||
variable_expression = name + skip( maybe( code_start + maybe( number ) + code_end ) ) + skip( operator('=') ) + oneplus( variable_contents ) + skip( eol ) >> set_variable | |||
#| <capability name> => <c function>; | |||
capability_arguments = name + skip( operator(':') ) + number + skip( maybe( comma ) ) | |||
@@ -683,11 +692,14 @@ operatorTriggerResult = operator(':') | operator(':+') | operator(':-') | operat | |||
scanCode_expression = triggerCode_outerList + operatorTriggerResult + resultCode_outerList + skip( eol ) >> map_scanCode | |||
usbCode_expression = triggerUSBCode_outerList + operatorTriggerResult + resultCode_outerList + skip( eol ) >> map_usbCode | |||
### Ignored expressions | |||
ignore_expression = scanCode_expanded | scanCode + operator('<=') + oneplus( position + maybe( skip( comma ) )) + eol | |||
def parse( tokenSequence ): | |||
"""Sequence(Token) -> object""" | |||
# Top-level Parser | |||
expression = scanCode_expression | usbCode_expression | variable_expression | capability_expression | define_expression | |||
expression = ignore_expression | scanCode_expression | usbCode_expression | variable_expression | capability_expression | define_expression | |||
kll_text = many( expression ) | |||
kll_file = maybe( kll_text ) + skip( finished ) | |||
@@ -708,8 +720,10 @@ def processKLLFile( filename ): | |||
try: | |||
tree = parse( tokenSequence ) | |||
except (NoParseError, KeyError) as err: | |||
print ( "{0} Parsing error in '{1}' - {2}".format( ERROR, filename, err ) ) | |||
sys.exit( 1 ) | |||
# Ignore data association expressions KLL 0.4+ required | |||
if err.token.value != '<=': | |||
print ( "{0} Parsing error in '{1}' - {2}".format( ERROR, filename, err ) ) | |||
sys.exit( 1 ) | |||
### Misc Utility Functions ### |