compiler/PPCTokenizingConfiguration.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Mon, 24 Aug 2015 15:34:14 +0100
changeset 524 f6f68d32de73
parent 515 b5316ef15274
child 525 751532c8f3db
permissions -rw-r--r--
Merged in PetitCompiler-JanVrany.170, PetitCompiler-Tests-JanKurs.116, PetitCompiler-Extras-Tests-JanKurs.29, PetitCompiler-Benchmarks-JanKurs.19 Name: PetitCompiler-JanVrany.170 Author: JanVrany Time: 24-08-2015, 03:19:51.340 PM UUID: c20a744f-3b41-4aaa-bb8a-71ce74a2a952 Name: PetitCompiler-Tests-JanKurs.116 Author: JanKurs Time: 24-08-2015, 11:37:54.332 AM UUID: 549e0927-358a-4a1b-8270-050ccfcb4217 Name: PetitCompiler-Extras-Tests-JanKurs.29 Author: JanKurs Time: 24-08-2015, 11:36:52.503 AM UUID: ea1dbb67-f884-4237-8f34-adb0677c0954 Name: PetitCompiler-Benchmarks-JanKurs.19 Author: JanKurs Time: 24-08-2015, 11:48:47.045 AM UUID: 1c342fdb-8ddd-4104-9c47-a8f589c51694

"{ Package: 'stx:goodies/petitparser/compiler' }"

"{ NameSpace: Smalltalk }"

PPCConfiguration subclass:#PPCTokenizingConfiguration
	instanceVariableNames:'scannerClazz parserClazz idGen'
	classVariableNames:''
	poolDictionaries:''
	category:'PetitCompiler-Core'
!

!PPCTokenizingConfiguration methodsFor:'compiling'!

arguments: args
    super arguments: args.
!

buildClass: clazz
    |  builder |
    builder := PPCClassBuilder new.
    
    builder compiledClassName: clazz name.
    builder compiledSuperclass: clazz superclass.
    builder methodDictionary: clazz methodDictionary.
    builder constants: clazz constants.

    ^ builder compileClass.	
!

invokePhases
    self toPPCIr.
    self createTokens.
    self cacheFirstFollow.
    self createLL1Choices.
    self tokenize.
    self merge.
    self specialize.
    self createRecognizingComponents.
    self specialize.
    self inline.
    self merge.
    self check.	
    self cacheFirstFollow.
    self buildParserClazz.
    self unmarkConsumeTokensForInline.
    self createFSAs.
    self buildScannerTokens.
    self buildScannerScans.	
    self generateScanner.
    self generateParser.
! !

!PPCTokenizingConfiguration methodsFor:'initialization'!

fillInClazzes
    parserClazz name: arguments parserName.
    parserClazz superclass: PPTokenizingCompiledParser.
    
    scannerClazz name: arguments scannerName.
    scannerClazz superclass: arguments scannerSuperclass.
    
!

initialize
    super initialize.
    
    parserClazz := PPCClass new.
    scannerClazz := PPCClass new.
    
    idGen := PPCIdGenerator new.
    
    "The parser and scanner share the same id generator in order
     to use same names for tokens.
    "
    parserClazz idGen: idGen.
    scannerClazz idGen: idGen.
! !

!PPCTokenizingConfiguration methodsFor:'phases'!

buildParserClazz
    | rootMethod |
    rootMethod := PPCTokenizingCodeGenerator new
        clazz: parserClazz;
        arguments: arguments;
        visit: ir.
        
    parserClazz propertyAt: #rootMethod put: rootMethod
!

buildScannerScans
    | fsas  generator |
    
    "TODO JK: Perhpas write separate visitor for this?"
    fsas := IdentitySet new.
    fsas addAll: (ir allNodes select: [ :node | node hasFsa ] thenCollect: [:node | node fsa]).
    fsas addAll: (ir allNodes select: [ :node | node hasNextFsa ] thenCollect: [:node | node nextFsa]).
    fsas := fsas reject: [ :fsa | fsa hasDistinctRetvals not ].
    
    generator := PPCScannerCodeGenerator new
        clazz: scannerClazz;
        arguments: arguments;
        yourself.
        
    fsas do: [ :fsa | generator generate: fsa ].
!

buildScannerTokens
    | generator  |
    generator :=  PPCTokenCodeGenerator new
        clazz: scannerClazz;
        arguments: arguments;
        yourself.

    generator visit: ir.
!

createFSAs
    ir := PPCFSAVisitor new
        idGen: idGen;
        visit: ir.

    self remember: (self copyTree: ir) as: #withFSAs
!

createLL1Choices
    self flag: 'This phase needs revisit and update'.
    
    ir :=  PPCLL1Visitor new
        arguments: arguments;
        visit: ir.
        
    self remember: (self copyTree: ir) as: #LL1
!

generateParser
    | parserClass rootMethod |
    arguments generate ifFalse: [ ^ self ].
    rootMethod := parserClazz propertyAt: #rootMethod.
    
    parserClazz name: arguments parserName.
    parserClazz superclass: arguments parserSuperclass.
    
    parserClass := self buildClass: parserClazz.
    parserClass startSymbol: rootMethod methodName.

    self remember: parserClass as: #parser.
    ir := parserClass new

    
!

generateScanner
    | scanner |
    arguments generate ifFalse: [ ^ self ].
    
    scannerClazz name: arguments scannerName.
    scannerClazz superclass: arguments scannerSuperclass.
    
    scanner := (self buildClass: scannerClazz).
    parserClazz addConstant: scanner as: #scannerClass.
    
    ir := scanner.
    
    self remember: scanner as: #scanner
!

tokenize
    "
        This will try transform the parser into the tokenizing parser
    "
    arguments tokenize ifFalse: [ ^ self ] .
    
    ir :=  PPCTokenizingVisitor new
        arguments: arguments;
        visit: ir.
        
        
    self remember: (self copyTree: ir) as: #tokenize
!

unmarkConsumeTokensForInline
    "TODO JK: Hack alert, use visitor, or at leas isTokenConsume"
    ir allNodesDo: [ :node |
        node class == PPCTokenConsumeNode ifTrue: [ 
            node unmarkForInline
        ]
    ]
! !