├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml ├── settings.xml └── src ├── main └── antlr4 │ └── com │ └── github │ └── vlsi │ └── iec61131 │ └── parser │ └── IEC61131.g4 └── test └── java └── com └── github └── vlsi └── iec61131 └── parser └── ParserTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | ~ 2 | target 3 | .idea 4 | *.iml 5 | .classpath.txt 6 | .fullclasspath.txt 7 | 8 | # eclipse 9 | .project 10 | .buildpath 11 | .classpath 12 | .settings 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | jdk: 4 | - openjdk7 5 | - oraclejdk8 6 | before_cache: rm -rf $HOME/.m2/repository/com/github/vlsi/iec61131 7 | cache: 8 | directories: 9 | - $HOME/.m2/repository 10 | env: 11 | global: 12 | - secure: igP6AWQIBqYXrpxE0QKsjd7JqHA+Sp3iDLImt/ENtwMTMgQFKZdcMDwLtZwKnPHoXMeHnPLHhVZwmBUeGa1dRAZ/TbpPb2YTEq27MIij0GcCU/lwK6orA16pFJwL201mpyCszjRAY8EkSPGmU7K6s77NL7qcXaXIJF3QJIfYYENhseZrY1Kx2R54Mtkm2S5rNy1+nXzwAHphQioLSkO2/N0CTuiiM2i2Gf5EW2/LiRGn9tgWGG0RE6ukqQnkqLkfrMMcUAHPjRNhf2Z3Crx1nVbeaUzsDlYMY9jGREeXWJUay1A0M/CTvnLPx/Y6jz7YnAm67CgM5aRSheoGgJ0qs54Fzx5YqJMWPW7PqeTLE7Ly8MImvNglCpYCPN3OtM0XJzVnZPjlmldNSRayJTdJrCA0TFEYN3Bc47/nYi+BVO3G+F2S5lHO+kABbkn/JZdXkKT37GycDubqTOzzKluYXYR6jSrWzOq1hgOkuglAEJmNbE7PrtuCNNBbTR1TZhy0vjxJIn6oGf/mYXr+WwBDRwUCAtWwEvi+Wvnl1HWgopuA9snnUHeFXOe4gC0AGnXMWpgCLma/1lMlvFgV4HKUqw7QR6qZWrd7SZuh5MBZItZfsSSiEkH5fBA5dh3Nyg4YzpsEQsZEW6YGLYYIVJ3iKYWL/oEqu7wcuwvozYRkxSk= 13 | - secure: gAGjDZJwB3H8YQde/fv/GHdJ46vdS/yTdMtLH6oli0P/bYdKewEtKClV7v7lbHCIHIzh2HWNf17E+9AfV7bmQRFxMd6oZVY4NAIhW9y6ofCHaCuEWS0hi1Gx7qeLXj2olRuA6Q3vB9ybiaNhr/R+gcm93QXKteEu8tTunuGKPME6pc5B1q9d5+MRDNB43UKgrVJquQ3t4AXx9g9AJGr/CxStPcao3TYOXDlFRe7l7MCATUswK+CCKB5MruCvVARuH95gJ3QYYpIRz9D8mJcXNv/F3LSZDktO0iT3DzxAhbH2ZwB8sewz0T/+HGc+l1XdnW0qsJ9Q/cbbK+0KoaK68mGuLIE8WQnquNjQWNtdjKuT1WS7ajOVrfc/P6LPOp0HhacG4HS84JURzkfff7E2gVczkYUEtzohgelMXNlBRALseMD9hRY+DVCQzcHxv8hO7wWheBv6qImcd/Vn8aH1hZ7o6bHTY+cHNpYZi1q4UOaQ3aVN53u17WEv4MF7SxSrjSS9Fh9eLTfCzDYJCw2MMqWfQukFmhrzkE4nfbjUzVNI6S7J61P2JhWAvAoFHjAKv6AMq3lD5m/NQ2KVB6HN0j3CRwVNizsoEdTsW2tiWiOdOwYrOo3cLzknr5xMFYBu2BucDTRtSvpFrvmhGLj9l97ey6ItGWfPmLG/uvf7DwE= 14 | 15 | after_success: 16 | - "test $TRAVIS_PULL_REQUEST == 'false' && test $TRAVIS_BRANCH == 'master' && test $TRAVIS_JDK_VERSION == 'openjdk7' && mvn clean deploy -B -V --settings settings.xml -DskipTests" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/vlsi/iec61131-parser.svg?branch=master)](https://travis-ci.org/vlsi/iec61131-parser) 2 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.vlsi.iec61131/parser/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.vlsi.iec61131/parser) 3 | 4 | IEC61131 parsers 5 | ================ 6 | 7 | About 8 | ----- 9 | This is a ANTLRv4 grammar for IEC61131-3 languages. 10 | The main aim is to parse ST grammar. 11 | 12 | Usage 13 | ----- 14 | 15 | Add maven dependency: 16 | ```xml 17 | 18 | com.github.vlsi.iec61131 19 | parser 20 | 1.0.0-SNAPSHOT 21 | 22 | ``` 23 | 24 | Sample 25 | ------ 26 | 27 | ```java 28 | ANTLRInputStream is = new ANTLRInputStream("FUNCTION abc : BOOL VAR_TEMP temp: INT; END_VAR"); 29 | IEC61131Lexer lex = new IEC61131Lexer(is); 30 | CommonTokenStream ts = new CommonTokenStream(lex); 31 | IEC61131Parser p = new IEC61131Parser(ts); 32 | 33 | IEC61131Parser.FunctionContext function = p.function(); 34 | 35 | Assert.assertEquals(function.name.getText(), "abc", "function name"); 36 | Assert.assertEquals(function.var_block().size(), 1, "1 block with variables"); 37 | IEC61131Parser.Var_blockContext varBlock = function.var_block(0); 38 | 39 | Assert.assertEquals(varBlock.temp, true, "var_temp -> temp.true"); 40 | Assert.assertEquals(varBlock.variable_declaration().size(), 1, "1 variable"); 41 | 42 | IEC61131Parser.Variable_declarationContext var = 43 | varBlock.variable_declaration(0); 44 | Assert.assertEquals(var.name.getText(), "temp", "variable name"); 45 | Assert.assertEquals(var.type.getText(), "INT", "variable type"); 46 | ``` 47 | 48 | License 49 | ------- 50 | 51 | This library is distributed under terms of MIT license. 52 | 53 | Changelog 54 | --------- 55 | 56 | v1.0.0 57 | * Initial version 58 | 59 | Author 60 | ------ 61 | Vladimir Sitnikov -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.github.vlsi.iec61131 7 | parser 8 | 1.0.0-SNAPSHOT 9 | jar 10 | 11 | IEC61131 parser 12 | Parsers for IEC 61131-3 grammar 13 | https://github.com/vlsi/iec61131-parser 14 | 15 | 16 | UTF-8 17 | 1.7 18 | 19 | 20 | 21 | 22 | vlsi 23 | Vladimir Sitnikov 24 | 25 | 26 | 27 | 28 | 29 | MIT License 30 | http://www.opensource.org/licenses/mit-license.php 31 | repo 32 | 33 | 34 | 35 | 36 | https://github.com/vlsi/pgjdbc 37 | scm:git:https://github.com/vlsi/iec61131-parser.git 38 | scm:git:https://github.com/vlsi/iec61131-parser.git 39 | HEAD 40 | 41 | 42 | 43 | 44 | org.antlr 45 | antlr4 46 | 4.5.1-1 47 | 48 | 49 | 50 | org.testng 51 | testng 52 | 6.1.1 53 | test 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.codehaus.mojo 61 | build-helper-maven-plugin 62 | 1.9.1 63 | 64 | 65 | parse-version 66 | 67 | parse-version 68 | 69 | 70 | 71 | 72 | 73 | org.antlr 74 | antlr4-maven-plugin 75 | 4.5.1-1 76 | 77 | 78 | antlr 79 | 80 | antlr4 81 | 82 | 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-jar-plugin 88 | 2.5 89 | 90 | 91 | 92 | jar 93 | 94 | 95 | 96 | 97 | com.github.vlsi.iec61131.parser 98 | ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion} 99 | com.github.vlsi.iec61131.parser 100 | 101 | 102 | true 103 | 104 | 105 | 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-shade-plugin 110 | 2.2 111 | 112 | 113 | package 114 | 115 | shade 116 | 117 | 118 | true 119 | true 120 | complete 121 | 122 | 123 | 124 | com.github.vlsi.iec61131.parser 125 | ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion} 126 | com.github.vlsi.iec61131.parser 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | org.apache.maven.plugins 140 | maven-compiler-plugin 141 | 3.3 142 | 143 | ${java.target} 144 | ${java.target} 145 | 146 | 147 | 148 | org.apache.maven.plugins 149 | maven-gpg-plugin 150 | 1.6 151 | 152 | 153 | org.apache.maven.plugins 154 | maven-shade-plugin 155 | 2.2 156 | 157 | 158 | org.apache.maven.plugins 159 | maven-javadoc-plugin 160 | 2.10.3 161 | 162 | 163 | attach-javadocs 164 | 165 | jar 166 | 167 | 168 | 169 | 170 | 171 | org.apache.maven.plugins 172 | maven-source-plugin 173 | 2.4 174 | 175 | 181 | 182 | attach-sources 183 | none 184 | 185 | 186 | attach-sources-no-fork 187 | true 188 | 189 | jar-no-fork 190 | 191 | 192 | 193 | 194 | 195 | org.apache.maven.plugins 196 | maven-release-plugin 197 | 2.5.1 198 | 199 | true 200 | release-artifacts,release 201 | v@{project.version} 202 | 203 | 204 | 205 | org.apache.maven.scm 206 | maven-scm-provider-gitexe 207 | 1.9.2 208 | 209 | 210 | 211 | 212 | org.sonatype.plugins 213 | nexus-staging-maven-plugin 214 | 1.6.5 215 | true 216 | 217 | ossrh 218 | https://oss.sonatype.org/ 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | release-artifacts 228 | 229 | 230 | 231 | org.apache.maven.plugins 232 | maven-source-plugin 233 | 234 | 235 | org.apache.maven.plugins 236 | maven-javadoc-plugin 237 | 238 | 239 | 240 | 241 | 242 | 243 | release 244 | 245 | 246 | 247 | org.apache.maven.plugins 248 | maven-gpg-plugin 249 | 250 | 251 | sign-artifacts 252 | verify 253 | 254 | sign 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | mvn-release-perform-staging 265 | 266 | 267 | performRelease 268 | true 269 | 270 | 271 | 272 | 273 | 274 | org.sonatype.plugins 275 | nexus-staging-maven-plugin 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | ossrh-snapshots 285 | https://oss.sonatype.org/content/repositories/snapshots/ 286 | 287 | 288 | ossrh 289 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | ossrh-snapshots 9 | ${env.SONATYPE_USERNAME} 10 | ${env.SONATYPE_PASSWORD} 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/antlr4/com/github/vlsi/iec61131/parser/IEC61131.g4: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | grammar IEC61131; 8 | 9 | pou 10 | : function 11 | | function_block 12 | ; 13 | 14 | function: 'FUNCTION' name=ID ':' type=type_rule var_blocks+=var_block*; 15 | 16 | function_block: 17 | 'FUNCTION_BLOCK' name=ID 18 | var_blocks+=var_block*; 19 | 20 | var_block locals[boolean input, boolean output, boolean temp] 21 | : ('VAR' 22 | | { $input=true; } 'VAR_INPUT' 23 | | { $output=true; } 'VAR_OUTPUT' 24 | | { $input=$output=true; } 'VAR_INPUT_OUTPUT' 25 | | { $temp=true; } 'VAR_TEMP') 26 | ( variables+=variable_declaration* 'END_VAR'); 27 | 28 | type_rule: 29 | name=ID #simpleType 30 | | array=array_type #arrayType 31 | | pointer=pointer_type #pointerType 32 | ; 33 | 34 | array_type 35 | : 'ARRAY' '[' ranges+=range (',' ranges+=range)* ']' 'OF' type=type_rule; 36 | 37 | range 38 | : lbound=integer_literal '..' ubound=integer_literal; 39 | 40 | pointer_type: 'POINTER' 'TO' type=type_rule; 41 | 42 | variable_declaration: 43 | names+=ID (',' names+=ID)* ':' type=type_rule (':=' initializer=variable_initializer)? ';' ; 44 | 45 | variable_initializer: 46 | literal; 47 | 48 | literal: 49 | numeric_literal | string_literal | boolean_literal; 50 | 51 | 52 | boolean_literal: 'TRUE' | 'FALSE'; 53 | 54 | numeric_literal 55 | : '-'? integer_literal 56 | | '-'? Floating_point_literal 57 | ; 58 | 59 | integer_literal 60 | : Binary_literal 61 | | Octal_literal 62 | | Decimal_literal 63 | | Pure_decimal_digits 64 | | Hexadecimal_literal 65 | ; 66 | 67 | Binary_literal : '2#' Binary_digit Binary_literal_characters? ; 68 | fragment Binary_digit : [01] ; 69 | fragment Binary_literal_character : Binary_digit | '_' ; 70 | fragment Binary_literal_characters : Binary_literal_character+ ; 71 | 72 | Octal_literal : '8#' Octal_digit Octal_literal_characters? ; 73 | fragment Octal_digit : [0-7] ; 74 | fragment Octal_literal_character : Octal_digit | '_' ; 75 | fragment Octal_literal_characters : Octal_literal_character+ ; 76 | 77 | Decimal_literal : [0-9] [0-9_]* ; 78 | Pure_decimal_digits : [0-9]+ ; 79 | fragment Decimal_digit : [0-9] ; 80 | fragment Decimal_literal_character : Decimal_digit | '_' ; 81 | fragment Decimal_literal_characters : Decimal_literal_character+ ; 82 | 83 | Hexadecimal_literal : '16#' Hexadecimal_digit Hexadecimal_literal_characters? ; 84 | fragment Hexadecimal_digit : [0-9a-fA-F] ; 85 | fragment Hexadecimal_literal_character : Hexadecimal_digit | '_' ; 86 | fragment Hexadecimal_literal_characters : Hexadecimal_literal_character+ ; 87 | 88 | Floating_point_literal 89 | : Decimal_literal Decimal_fraction? Decimal_exponent? 90 | ; 91 | 92 | fragment Decimal_fraction : '.' Decimal_literal ; 93 | fragment Decimal_exponent : Floating_point_e Sign? Decimal_literal ; 94 | fragment Floating_point_e : [eE] ; 95 | fragment Floating_point_p : [pP] ; 96 | fragment Sign : [+\-] ; 97 | 98 | string_literal 99 | : Static_string_literal 100 | ; 101 | Static_string_literal : '\'' Quoted_text? '\'' ; 102 | fragment Quoted_text : Quoted_text_item+ ; 103 | fragment Quoted_text_item 104 | : Escaped_character 105 | | ~["\n\r\\] 106 | ; 107 | fragment 108 | Escaped_character 109 | : '$' [$'LNPRT] 110 | | '$' Hexadecimal_digit Hexadecimal_digit 111 | ; 112 | 113 | ID: [A-Za-z][A-Za-z_0-9]*; 114 | 115 | WS : [ \n\r\t]+ -> channel(HIDDEN) ; 116 | Block_comment : '(*' (Block_comment|.)*? '*)' -> channel(HIDDEN) ; // nesting comments allowed -------------------------------------------------------------------------------- /src/test/java/com/github/vlsi/iec61131/parser/ParserTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vlsi.iec61131.parser; 2 | 3 | import org.antlr.v4.runtime.ANTLRInputStream; 4 | import org.antlr.v4.runtime.CommonTokenStream; 5 | import org.testng.Assert; 6 | import org.testng.annotations.Test; 7 | 8 | public class ParserTest { 9 | @Test 10 | public void simple() { 11 | IEC61131Parser p = getIec61131Parser("FUNCTION abc : BOOL VAR_TEMP temp: INT; END_VAR"); 12 | IEC61131Parser.FunctionContext function = p.function(); 13 | 14 | Assert.assertEquals(function.name.getText(), "abc", "function name"); 15 | Assert.assertEquals(function.var_block().size(), 1, "1 block with variables"); 16 | IEC61131Parser.Var_blockContext varBlock = function.var_block(0); 17 | 18 | Assert.assertEquals(varBlock.temp, true, "var_temp -> temp.true"); 19 | Assert.assertEquals(varBlock.variable_declaration().size(), 1, "1 variable"); 20 | 21 | IEC61131Parser.Variable_declarationContext var = 22 | varBlock.variable_declaration(0); 23 | Assert.assertEquals(var.names.size(), 1, "there should be single variable"); 24 | Assert.assertEquals(var.names.get(0).getText(), "temp", "variable name"); 25 | Assert.assertEquals(var.type.getText(), "INT", "variable type"); 26 | } 27 | 28 | @Test 29 | public void arrayVariable() { 30 | IEC61131Parser p = getIec61131Parser("temp: ARRAY[1..2, 4..6] OF BOOL;"); 31 | IEC61131Parser.Variable_declarationContext var = p.variable_declaration(); 32 | Assert.assertEquals(var.type.getClass(), IEC61131Parser.ArrayTypeContext.class, 33 | "type should be array"); 34 | IEC61131Parser.ArrayTypeContext ary = (IEC61131Parser.ArrayTypeContext) var.type; 35 | Assert.assertEquals(ary.array.ranges.size(), 2, "1..2, 4..6 -> two ranges"); 36 | } 37 | 38 | private IEC61131Parser getIec61131Parser(String input) { 39 | ANTLRInputStream is = new ANTLRInputStream(input); 40 | IEC61131Lexer lex = new IEC61131Lexer(is); 41 | CommonTokenStream ts = new CommonTokenStream(lex); 42 | return new IEC61131Parser(ts); 43 | } 44 | } 45 | --------------------------------------------------------------------------------