Add initial ANTLR setup + lex/parser

This commit is contained in:
Kenzie Togami 2019-10-13 02:02:47 -07:00
parent 21f3d967c3
commit 7d52374fc0
No known key found for this signature in database
GPG Key ID: 5D200B325E157A81
2 changed files with 213 additions and 0 deletions

View File

@ -1,7 +1,10 @@
import org.gradle.plugins.ide.idea.model.IdeaModel
plugins {
id("java-library")
id("net.ltgt.apt-eclipse")
id("net.ltgt.apt-idea")
id("antlr")
}
applyPlatformAndCoreConfiguration()
@ -23,6 +26,10 @@ dependencies {
"compile"("org.slf4j:slf4j-api:1.7.26")
"compile"("it.unimi.dsi:fastutil:8.2.1")
val antlrVersion = "4.7.2"
"antlr"("org.antlr:antlr4:$antlrVersion")
"implementation"("org.antlr:antlr4-runtime:$antlrVersion")
"compileOnly"(project(":worldedit-libs:core:ap"))
"annotationProcessor"(project(":worldedit-libs:core:ap"))
// ensure this is on the classpath for the AP
@ -36,6 +43,26 @@ tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Aarg.name.key.prefix=")
}
tasks.named<AntlrTask>("generateGrammarSource").configure {
val pkg = "com.sk89q.worldedit.antlr"
outputDirectory = file("build/generated-src/antlr/main/${pkg.replace('.', '/')}")
arguments = listOf(
"-visitor", "-package", pkg,
"-Xexact-output-dir"
)
}
// Give intellij info about where ANTLR code comes from
plugins.withId("idea") {
configure<IdeaModel> {
afterEvaluate {
module.sourceDirs.add(file("src/main/antlr"))
module.sourceDirs.add(file("build/generated-src/antlr/main"))
module.generatedSourceDirs.add(file("build/generated-src/antlr/main"))
}
}
}
sourceSets {
main {
java {

View File

@ -0,0 +1,186 @@
grammar Expression;
// Lexer tokens:
PLUS : '+' ;
MINUS : '-' ;
TIMES : '*' ;
DIVIDE : '/' ;
MODULO : '%' ;
POWER : '^' | '**' ;
LEFT_SHIFT : '<<' ;
RIGHT_SHIFT : '>>' ;
ASSIGN : '=' ;
COMPLEMENT : '~' ;
PLUS_ASSIGN : '+=' ;
MINUS_ASSIGN : '-=' ;
TIMES_ASSIGN : '*=' ;
DIVIDE_ASSIGN : '/=' ;
MODULO_ASSIGN : '%=' ;
POWER_ASSIGN : '^=' ;
EQUAL : '==' ;
NOT_EQUAL : '!=' ;
NEAR : '~=' ;
LESS_THAN : '<' ;
LESS_THAN_OR_EQUAL : '<=' ;
GREATER_THAN : '>' ;
GREATER_THAN_OR_EQUAL : '>=' ;
// SC = "Short Circuit"
// Non-SC variants not currently implemented.
AND_SC : '&&' ;
OR_SC : '||' ;
INCREMENT : '++' ;
DECREMENT : '--' ;
COMMA : ',' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
OPEN_BRACKET : '{' ;
CLOSE_BRACKET : '}' ;
SEMI_COLON : ';' ;
QUESTION_MARK : '?' ;
COLON : ':' ;
EXCLAMATION_MARK : '!' ;
IF : 'if' ;
ELSE : 'else' ;
WHILE : 'while' ;
DO : 'do' ;
FOR : 'for' ;
BREAK : 'break' ;
CONTINUE : 'continue' ;
RETURN : 'return' ;
SWITCH : 'switch' ;
CASE : 'case' ;
DEFAULT : 'default' ;
fragment DIGIT : [0-9] ;
fragment SIGN : [+-] ;
fragment EXP_CHAR : [eE] ;
fragment DECIMAL : '.' DIGIT+ ( EXP_CHAR SIGN? DIGIT+ )? ;
// All numbers are treated the same. No int/dec divide.
NUMBER : SIGN? ( DIGIT+ DECIMAL? | DECIMAL ) ;
ID : [A-Za-z] [0-9A-Za-z_]* ;
WS : [ \t\r\n\u000C]+ -> skip ;
// Parser rules:
/**
* All statements parseable from the input. Forces consumption of EOF token.
*/
allStatements : statements EOF ;
statements : statement+ ;
statement
: block
| ifStatement
| whileStatement
| doStatement
| forStatement
| breakStatement
| continueStatement
| returnStatement
| switchStatement
| expressionStatement
| SEMI_COLON
;
block : '{' statements '}' ;
ifStatement : IF '(' expression ')' statement ( ELSE statement ) ;
whileStatement : WHILE '(' expression ')' statement ;
doStatement : DO statement WHILE '(' expression ')' SEMI_COLON ;
forStatement
: FOR '('
// C-style for loop
( expression ';' expression ';' expression
// Range for loop
| ID ASSIGN ID ',' ID
)
')' statement ;
breakStatement : BREAK ;
continueStatement : CONTINUE ;
returnStatement : RETURN expression? ;
switchStatement : SWITCH '(' expression ')' '{' (switchLabel ':' statements )+ '}' ;
switchLabel
: CASE constantExpression
| DEFAULT
;
expressionStatement : expression SEMI_COLON ;
expression
: constantExpression
| functionCall
| identifierExpression
| '(' expression ')'
| unaryOp expression
| identifierExpression binaryAssignOp expression
| expression binaryOp expression
| expression postUnaryOp
;
constantExpression : NUMBER ;
functionCall : ID '(' (expression ( ',' expression )*)? ')' ;
identifierExpression : ID ;
unaryOp
: MINUS
| EXCLAMATION_MARK
| COMPLEMENT
| INCREMENT
| DECREMENT
;
postUnaryOp
: INCREMENT
| DECREMENT
| EXCLAMATION_MARK
;
binaryOp
: POWER
| TIMES
| DIVIDE
| MODULO
| PLUS
| MINUS
| LEFT_SHIFT
| RIGHT_SHIFT
| LESS_THAN
| GREATER_THAN
| LESS_THAN_OR_EQUAL
| GREATER_THAN_OR_EQUAL
| EQUAL
| NOT_EQUAL
| NEAR
| AND_SC
| OR_SC
;
binaryAssignOp
: ASSIGN
| PLUS_ASSIGN
| MINUS_ASSIGN
| TIMES_ASSIGN
| DIVIDE_ASSIGN
| MODULO_ASSIGN
| POWER_ASSIGN
;