Parse a small Java-like subset into semantic code fragments.
What it shows
Typedistinguishes reference types, primitive types, and arrays.Expressioncovers literals, identifiers, method calls, arithmetic, and comparisons.CodeElementcomposes blocks,if/else, methods, classes, and comments.- Method parameters, modifiers, statements, and block contents are repeatable fields.
Try adding a simple declaration or another System.out.println(...) call.
Specs
spec.yml
$flags: [ 'WORD_BOUNDARY', 'FLEXIBLE_WHITESPACE' ]
Comment: ['//.*', '(?s)/\*.*?\*/']
Keyword:
Class: 'class'
If: 'if'
Else: 'else'
For: 'for'
While: 'while'
Try: 'try'
Catch: 'catch'
Finally: 'finally'
Return: 'return'
Throw: 'throw'
Modifier:
Public: 'public'
Private: 'private'
Protected: 'protected'
Static: 'static'
Final: 'final'
Abstract: 'abstract'
Type:
Reference:
String: 'String'
System: 'System'
ArithmeticException: 'ArithmeticException'
Primitive:
Void: 'void'
Boolean: 'boolean'
Int: 'int'
Long: 'long'
Double: 'double'
Char: 'char'
Array:
$fields:
elementType: Type
$patterns: '#{elementType}\[\]'
Expression:
Identifier: '${!Keyword}[A-Za-z_][A-Za-z0-9_]*'
StringLiteral: '"([^"\\]|\\.)*"'
NumberLiteral: '\d+(\.\d+)?'
BooleanLiteral: 'true|false'
NullLiteral: 'null'
MethodCall:
$flags: OPTIONAL_WHITESPACE
$types:
MethodReceiver: '(${Type::Reference}|${Expression::Identifier})(\.${Expression::Identifier})*'
$fields:
receiver: MethodReceiver
methodName: Expression::Identifier
arguments: Expression[]
$patterns:
- '#{receiver}\.#{methodName}\((#{arguments}(, #{arguments})*)?\)'
- '#{methodName}\((#{arguments}(, #{arguments})*)?\)'
Operation:
Binary:
$flags: OPTIONAL_WHITESPACE
$fields:
left: Expression
right: Expression
Addition: '#{left} \+ #{right}'
Subtraction: '#{left} - #{right}'
Multiplication: '#{left} \* #{right}'
Division: '#{left} / #{right}'
Unary:
$fields:
value: Expression
Increment: '#{value}\+\+'
Decrement: '#{value}--'
Comparison:
$flags: OPTIONAL_WHITESPACE
$fields:
left: Expression
right: Expression
Equality: '#{left} == #{right}'
Inequality: '#{left} != #{right}'
LessThan: '#{left} < #{right}'
GreaterThan: '#{left} > #{right}'
LessOrEqual: '#{left} <= #{right}'
GreaterOrEqual: '#{left} >= #{right}'
Parameter:
$fields:
type: Type
name: Expression::Identifier
$patterns: '#{type} #{name}(?=,|\))'
CodeElement:
Comment: '${Comment}'
MethodCallStatement:
$flags: OPTIONAL_WHITESPACE
$fields:
call: Expression::MethodCall
$patterns: '#{call};'
VariableDeclaration:
$fields:
type: Type
name: Expression::Identifier
value: Expression
$patterns: '#{type} #{name} = #{value};'
Block:
$flags: OPTIONAL_WHITESPACE
$fields:
statements: CodeElement[]
$patterns: '\{ (#{statements}( #{statements})*)? \}'
ReturnStatement:
$fields:
value: Expression
$patterns: '${Keyword::Return} #{value};'
ThrowStatement:
$fields:
value: Expression
$patterns: '${Keyword::Throw} #{value};'
IfElseStatement:
$fields:
condition: Expression::Comparison
ifBody: CodeElement
elseBody: CodeElement
$patterns: '${Keyword::If} \(#{condition}\) #{ifBody}( ${Keyword::Else} #{elseBody})?'
ForStatement:
$fields:
type: Type
name: Expression::Identifier
initialValue: Expression
condition: Expression::Comparison
step: Expression::Operation::Unary::Increment
body: CodeElement
$patterns: '${Keyword::For} \(#{type} #{name} = #{initialValue}; #{condition}; #{step}\)\s*#{body}'
WhileStatement:
$fields:
condition: Expression::Comparison
body: CodeElement
$patterns: '${Keyword::While} \(#{condition}\) #{body}'
TryCatchFinallyStatement:
$fields:
tryBody: CodeElement
exception: Parameter
catchBody: CodeElement
finallyBody: CodeElement
$patterns: '${Keyword::Try} #{tryBody}( ${Keyword::Catch} \(#{exception}\) #{catchBody})?( ${Keyword::Finally} #{finallyBody})?'
MethodDeclaration:
$fields:
modifiers: Modifier[]
returnType: Type
name: Expression::Identifier
parameters: Parameter[]
body: CodeElement::Block
$patterns: '(#{modifiers} )*#{returnType} #{name}\((#{parameters}(, #{parameters})*)?\) #{body}'
ClassDeclaration:
$fields:
modifiers: Modifier[]
name: Expression::Identifier
body: CodeElement::Block
$patterns: '(#{modifiers} )*${Keyword::Class} #{name} #{body}'Try it liveOpen Java Code Fragments in StudioTweak the spec, paste your own input, and see the parse tree update in real time.