Archived
1
0

Updating KLL 0.5c lexer

- 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 NoParseError
This commit is contained in:
Jacob Alexander 2016-10-09 22:00:30 -07:00
parent d7b7752dc1
commit 3cd55cf5a4
7 changed files with 44 additions and 19 deletions

View File

@ -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

View File

@ -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]*', ) ),
]

View File

@ -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 ) )

View File

@ -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;

View File

@ -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 );

View File

@ -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

26
kll.py
View File

@ -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 ###