<commit_before>// Copyright 2015-2021, University of Colorado Boulder

/**
 * TODO: Relocate code in this file that doesn't have to do with configuring the app, setting up routes, etc. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
 * Main entry point for PhET translation web app. This is where Express.js gets configured and the routes are set up.
 *
 * @author John Blanco
 * @author Aaron Davis
 * @author Liam Mulhall
 */

// modules
const bodyParser = require( 'body-parser' ); // eslint-disable-line require-statement-match
const childProcess = require( 'child_process' ); // eslint-disable-line require-statement-match
const cookieParser = require( 'cookie-parser' ); // eslint-disable-line require-statement-match
const doT = require( 'express-dot' ); // eslint-disable-line require-statement-match
const express = require( 'express' );
const getRosettaConfig = require( './getRosettaConfig' );
const { Pool } = require( 'pg' ); // eslint-disable-line
const RosettaConstants = require( './RosettaConstants' );
const winston = require( 'winston' );
const ensureValidSession = require( './ensureValidSession' );

// order-dependent Modules
const session = require( 'express-session' ); // eslint-disable-line require-statement-match
const MemoryStore = require( 'memorystore' )( session );

// constants
const LISTEN_PORT = 16372;
const { format } = winston;

//===========================================================================//
// Configure Winston (the logger). Use Winston to display information.       //
//===========================================================================//

// Configure the logger. Uses default logging level, which can be updated once configuration is read.
const consoleTransport = new winston.transports.Console( {
  format: format.combine(
    format.printf( i => `${i.level} - ${i.message}` )
  )
} );
winston.add( consoleTransport );

// Add a global handler for unhandled promise rejections.
process.on( 'unhandledRejection', error => {

  // If these are logged, issues should be tracked down and fixed.
  winston.error( `Unhandled rejection. Error Message: ${error.message}` );
  winston.error( `Error Stack: ${error.stack}` );
} );

// Log startup message.
winston.info( '========== Rosetta is starting up! ==========' );
winston.info( `Node Version ${process.version}` );

// Log Rosetta's SHA. This might make it easier to duplicate issues and track them down.
try {

  // For some reason, "sha.toString()" has a newline. I want the log to look nice, so I'm taking it out.
  let sha = childProcess.execSync( 'git rev-parse HEAD' );
  sha = sha.toString();
  sha = sha.replace( /\r?\n|\r/, '' );
  winston.info( `Current SHA is ${sha}` );
}
catch( error ) {
  winston.warn( `Unable to get SHA from Git. Error: ${error}` );
}

// TODO: Move this to a more appropriate location. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// TODO: Determine if setting a variable for the config is preferable to this approach. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Get configuration and assign it to a global. This also sets up some process variables.
global.config = getRosettaConfig();

// Log the config.
winston.info( 'Check your config below and make sure it looks correct!' );
winston.info( JSON.stringify( global.config, null, 2 ) );

// TODO: Determine if it's possible to get the config before setting up the logger. (So we don't have to update it.) See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Update the logging level in case it was set in the config info.
// If you want to use QUnit, you should set the loggingLevel in your config to emerg
consoleTransport.level = global.config.loggingLevel;

// TODO: Move this into its own file. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Check that the database is running and that a basic query can be performed.
winston.info( 'Testing database connection...' );
const pool = new Pool( {
  connectionTimeoutMillis: RosettaConstants.DATABASE_QUERY_TIMEOUT
} );
pool.query( 'SELECT NOW();', ( error, result ) => {
  if ( error ) {
    winston.error( `Database test using SELECT NOW() failed. Error: ${JSON.stringify( error )}` );
    winston.error( 'Short term storage will be unavailable.' );
  }
  else {
    winston.info( `Database test using SELECT NOW() succeeded. Now: ${result.rows[ 0 ].now}` );
  }
} );

//===========================================================================//
// Set up the app.                                                           //
//===========================================================================//

// Create and configure the Express.js app.
const app = express();
app.set( 'views', `${__dirname}/../html/views` );
app.set( 'view engine', 'dot' );
app.engine( 'html', doT.__express );

// Set static directories for CSS, images, and JavaScript.
app.use( '/translate/css', express.static( `${__dirname}/../css` ) );
app.use( '/translate/img', express.static( `${__dirname}/../img` ) );
app.use( '/translate/js', express.static( __dirname ) );

// Set up handling for cookies.
app.use( cookieParser() );
app.use( session( {
  secret: global.config.rosettaSessionSecret,
  resave: false,
  saveUninitialized: false,
  store: new MemoryStore( {
    checkPeriod: 86400000 // In milliseconds. Set to 1 day.
  } )
} ) );
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded( { extended: false } ) );

//===========================================================================//
// Set up the routes. The order in which they are set up matters!            //
//===========================================================================//

// Add route handlers. Must be after global.config has been initialized and logger configured.
const routeHandlers = require( `${__dirname}/routeHandlers` );

// Set up route for the 'down for maintenance' page.
if ( !global.config.enabled ) {
  app.get( '/translate', routeHandlers.showOfflinePage );
}

// Set up route for checking if a user is logged in.
app.get( '/translate*', ensureValidSession );

// Set up routes for debugging.
app.post( '/translate*', ( request, response, next ) => {
  winston.debug( `Post request received. URL: ${request.url}.` );
  next();
} );
app.get( '/translate*', ( request, response, next ) => {
  winston.debug( `Get request received. URL: ${request.url}.` );
  next();
} );

// Set up landing page for the translation utility.
app.get( '/translate', routeHandlers.chooseSimulationAndLanguage );

// Set up page where user can submit their translated strings.
app.get( '/translate/sim/:simName?/:targetLocale?', routeHandlers.renderTranslationPage );

// Set up post route for testing translated strings. This doesn't save the translated strings.
app.post( '/translate/sim/test/:simName?', routeHandlers.testStrings );

// Set up post route for short-term storage of strings.
app.post( '/translate/sim/save/:simName?/:targetLocale?', routeHandlers.saveStrings );

// Set up post route for long-term storage of strings.
app.post( '/translate/sim/:simName?/:targetLocale?', routeHandlers.submitStrings );

// Set up logout.
app.get( '/translate/logout', routeHandlers.logout );

// Trigger the build of a simulation for a given sim, locale, and user ID. Only used by team members to fix problems.
app.get( '/translate/trigger-build/:simName?/:targetLocale?/:userId?', routeHandlers.triggerBuild );

// Routes for info on untranslated strings.
app.get( '/translate/sim-string-report/:simName?/:targetLocale?/', routeHandlers.simStringReport );
app.get( '/translate/locale-string-report/:targetLocale?/', routeHandlers.localeStringReport );

// TODO: Move this when you're done.
app.get( '/translate/sse/', async function( req, res ) {
  res.set( {
    'Cache-Control': 'no-cache',
    'Content-Type': 'text/event-stream',
    'Connection': 'keep-alive'
  } );
  res.flushHeaders();
  let count = 0;
  while ( true ) {
    await new Promise( resolve => setTimeout( resolve, 1000 ) );
    res.write(`data: ${count}\n\n`);
    count++;
  }
} );

// Set up routes for incorrect URL patterns.
app.get( '/*', routeHandlers.pageNotFound );
app.post( '/*', routeHandlers.pageNotFound );

// Start the server.
app.listen( LISTEN_PORT, () => {
  winston.info( `Listening on port ${LISTEN_PORT}.` );
  winston.info( `Open your browser to http://localhost:${LISTEN_PORT}/translate` );
} );
<commit_msg>Suppressing lint errors.<commit_after>// Copyright 2015-2021, University of Colorado Boulder

/**
 * TODO: Relocate code in this file that doesn't have to do with configuring the app, setting up routes, etc. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
 * Main entry point for PhET translation web app. This is where Express.js gets configured and the routes are set up.
 *
 * @author John Blanco
 * @author Aaron Davis
 * @author Liam Mulhall
 */

// modules
const bodyParser = require( 'body-parser' ); // eslint-disable-line require-statement-match
const childProcess = require( 'child_process' ); // eslint-disable-line require-statement-match
const cookieParser = require( 'cookie-parser' ); // eslint-disable-line require-statement-match
const doT = require( 'express-dot' ); // eslint-disable-line require-statement-match
const express = require( 'express' );
const getRosettaConfig = require( './getRosettaConfig' );
const { Pool } = require( 'pg' ); // eslint-disable-line
const RosettaConstants = require( './RosettaConstants' );
const winston = require( 'winston' );
const ensureValidSession = require( './ensureValidSession' );

// order-dependent Modules
const session = require( 'express-session' ); // eslint-disable-line require-statement-match
const MemoryStore = require( 'memorystore' )( session );

// constants
const LISTEN_PORT = 16372;
const { format } = winston;

//===========================================================================//
// Configure Winston (the logger). Use Winston to display information.       //
//===========================================================================//

// Configure the logger. Uses default logging level, which can be updated once configuration is read.
const consoleTransport = new winston.transports.Console( {
  format: format.combine(
    format.printf( i => `${i.level} - ${i.message}` )
  )
} );
winston.add( consoleTransport );

// Add a global handler for unhandled promise rejections.
process.on( 'unhandledRejection', error => {

  // If these are logged, issues should be tracked down and fixed.
  winston.error( `Unhandled rejection. Error Message: ${error.message}` );
  winston.error( `Error Stack: ${error.stack}` );
} );

// Log startup message.
winston.info( '========== Rosetta is starting up! ==========' );
winston.info( `Node Version ${process.version}` );

// Log Rosetta's SHA. This might make it easier to duplicate issues and track them down.
try {

  // For some reason, "sha.toString()" has a newline. I want the log to look nice, so I'm taking it out.
  let sha = childProcess.execSync( 'git rev-parse HEAD' );
  sha = sha.toString();
  sha = sha.replace( /\r?\n|\r/, '' );
  winston.info( `Current SHA is ${sha}` );
}
catch( error ) {
  winston.warn( `Unable to get SHA from Git. Error: ${error}` );
}

// TODO: Move this to a more appropriate location. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// TODO: Determine if setting a variable for the config is preferable to this approach. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Get configuration and assign it to a global. This also sets up some process variables.
global.config = getRosettaConfig();

// Log the config.
winston.info( 'Check your config below and make sure it looks correct!' );
winston.info( JSON.stringify( global.config, null, 2 ) );

// TODO: Determine if it's possible to get the config before setting up the logger. (So we don't have to update it.) See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Update the logging level in case it was set in the config info.
// If you want to use QUnit, you should set the loggingLevel in your config to emerg
consoleTransport.level = global.config.loggingLevel;

// TODO: Move this into its own file. See https://github.com/phetsims/rosetta/issues/190#issuecomment-682169944.
// Check that the database is running and that a basic query can be performed.
winston.info( 'Testing database connection...' );
const pool = new Pool( {
  connectionTimeoutMillis: RosettaConstants.DATABASE_QUERY_TIMEOUT
} );
pool.query( 'SELECT NOW();', ( error, result ) => {
  if ( error ) {
    winston.error( `Database test using SELECT NOW() failed. Error: ${JSON.stringify( error )}` );
    winston.error( 'Short term storage will be unavailable.' );
  }
  else {
    winston.info( `Database test using SELECT NOW() succeeded. Now: ${result.rows[ 0 ].now}` );
  }
} );

//===========================================================================//
// Set up the app.                                                           //
//===========================================================================//

// Create and configure the Express.js app.
const app = express();
app.set( 'views', `${__dirname}/../html/views` );
app.set( 'view engine', 'dot' );
app.engine( 'html', doT.__express );

// Set static directories for CSS, images, and JavaScript.
app.use( '/translate/css', express.static( `${__dirname}/../css` ) );
app.use( '/translate/img', express.static( `${__dirname}/../img` ) );
app.use( '/translate/js', express.static( __dirname ) );

// Set up handling for cookies.
app.use( cookieParser() );
app.use( session( {
  secret: global.config.rosettaSessionSecret,
  resave: false,
  saveUninitialized: false,
  store: new MemoryStore( {
    checkPeriod: 86400000 // In milliseconds. Set to 1 day.
  } )
} ) );
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded( { extended: false } ) );

//===========================================================================//
// Set up the routes. The order in which they are set up matters!            //
//===========================================================================//

// Add route handlers. Must be after global.config has been initialized and logger configured.
const routeHandlers = require( `${__dirname}/routeHandlers` );

// Set up route for the 'down for maintenance' page.
if ( !global.config.enabled ) {
  app.get( '/translate', routeHandlers.showOfflinePage );
}

// Set up route for checking if a user is logged in.
app.get( '/translate*', ensureValidSession );

// Set up routes for debugging.
app.post( '/translate*', ( request, response, next ) => {
  winston.debug( `Post request received. URL: ${request.url}.` );
  next();
} );
app.get( '/translate*', ( request, response, next ) => {
  winston.debug( `Get request received. URL: ${request.url}.` );
  next();
} );

// Set up landing page for the translation utility.
app.get( '/translate', routeHandlers.chooseSimulationAndLanguage );

// Set up page where user can submit their translated strings.
app.get( '/translate/sim/:simName?/:targetLocale?', routeHandlers.renderTranslationPage );

// Set up post route for testing translated strings. This doesn't save the translated strings.
app.post( '/translate/sim/test/:simName?', routeHandlers.testStrings );

// Set up post route for short-term storage of strings.
app.post( '/translate/sim/save/:simName?/:targetLocale?', routeHandlers.saveStrings );

// Set up post route for long-term storage of strings.
app.post( '/translate/sim/:simName?/:targetLocale?', routeHandlers.submitStrings );

// Set up logout.
app.get( '/translate/logout', routeHandlers.logout );

// Trigger the build of a simulation for a given sim, locale, and user ID. Only used by team members to fix problems.
app.get( '/translate/trigger-build/:simName?/:targetLocale?/:userId?', routeHandlers.triggerBuild );

// Routes for info on untranslated strings.
app.get( '/translate/sim-string-report/:simName?/:targetLocale?/', routeHandlers.simStringReport );
app.get( '/translate/locale-string-report/:targetLocale?/', routeHandlers.localeStringReport );

// // TODO: Move this when you're done.
// app.get( '/translate/sse/', async ( req, res ) => {
//   res.set( {
//     'Cache-Control': 'no-cache',
//     'Content-Type': 'text/event-stream',
//     'Connection': 'keep-alive'
//   } );
//   res.flushHeaders();
//   let count = 0;
//   while ( true ) {
//     await new Promise( resolve => setTimeout( resolve, 1000 ) );
//     res.write( `data: ${count}\n\n` );
//     count++;
//   }
// } );

// Set up routes for incorrect URL patterns.
app.get( '/*', routeHandlers.pageNotFound );
app.post( '/*', routeHandlers.pageNotFound );

// Start the server.
app.listen( LISTEN_PORT, () => {
  winston.info( `Listening on port ${LISTEN_PORT}.` );
  winston.info( `Open your browser to http://localhost:${LISTEN_PORT}/translate` );
} );
<|endoftext|>


<commit_before>define(function() {

/**
 * Pending tasks.
 * @param {Object} store Object store
 * @constructor
 */
function Tasks(store) {
  this.store = store;
  this.tasks = this.store.init('tasks', {});
}

/**
 * Add a task into the given section
 * @param {String} section Section name
 * @param {Object} task Task to add
 */
Tasks.prototype.addTask = function(section, task) {
    if (!this.tasks.hasOwnProperty(section)) {
        this.tasks[section] = [];
    }
    task.seen = false;
    this.tasks[section].push(task);
    this.store.save();
};

/**
 * Remove a task from the given section
 * @param {String} section Section name
 * @param {Object} task Task to remove
 */
Tasks.prototype.removeTask = function(section, task) {
    if (!this.tasks.hasOwnProperty(section)) {
        return;
    }
    var idx = this.tasks[section].indexOf(task);
    this.tasks[section].splice(idx, 1);
    this.store.save();
};

/**
 * Get task objects for a section
 * @param {String} section Section name
 * @return {Object[]} List with the tasks.
 */
Tasks.prototype.getTasks = function(section) {
    if (this.tasks.hasOwnProperty(section)) {
        return this.tasks[section];
    }
    return [];
};

/**
 * Get the number of tasks in the given section
 * @param {String} section Section name
 * @return {Number} Number of tasks.
 */
Tasks.prototype.getOpenTasks = function(section) {
    var self = this;
    var nOpen = 0;
    Object.keys(this.tasks).forEach(function(section) {
        nOpen += self.tasks[section].length;
    });
    return nOpen;
};

/**
 * Clear all tasks
 */
Tasks.prototype.clear = function() {
    var self = this;
    Object.keys(this.tasks).forEach(function(section) {
        delete self.tasks[section];
    });
    this.store.save();
};

return Tasks;
});
<commit_msg>Properly retrieve open tasks for a given section.<commit_after>define(function() {

/**
 * Pending tasks.
 * @param {Object} store Object store
 * @constructor
 */
function Tasks(store) {
  this.store = store;
  this.tasks = this.store.init('tasks', {});
}

/**
 * Add a task into the given section
 * @param {String} section Section name
 * @param {Object} task Task to add
 */
Tasks.prototype.addTask = function(section, task) {
    if (!this.tasks.hasOwnProperty(section)) {
        this.tasks[section] = [];
    }
    task.seen = false;
    this.tasks[section].push(task);
    this.store.save();
};

/**
 * Remove a task from the given section
 * @param {String} section Section name
 * @param {Object} task Task to remove
 */
Tasks.prototype.removeTask = function(section, task) {
    if (!this.tasks.hasOwnProperty(section)) {
        return;
    }
    var idx = this.tasks[section].indexOf(task);
    this.tasks[section].splice(idx, 1);
    this.store.save();
};

/**
 * Get task objects for a section
 * @param {String} section Section name
 * @return {Object[]} List with the tasks.
 */
Tasks.prototype.getTasks = function(section) {
    if (this.tasks.hasOwnProperty(section)) {
        return this.tasks[section];
    }
    return [];
};

/**
 * Get the number of tasks in the given section
 * @param {String} section Section name or nothing to get all tasks
 * @return {Number} Number of tasks.
 */
Tasks.prototype.getOpenTasks = function(section) {
    if (section) {
        return self.tasks[section] ? self.tasks[section].length : 0;
    }
    var self = this;
    var nOpen = 0;
    Object.keys(this.tasks).forEach(function(section) {
        nOpen += self.tasks[section].length;
    });
    return nOpen;
};

/**
 * Clear all tasks
 */
Tasks.prototype.clear = function() {
    var self = this;
    Object.keys(this.tasks).forEach(function(section) {
        delete self.tasks[section];
    });
    this.store.save();
};

return Tasks;
});
<|endoftext|>


<commit_before>/************************************
* scanner.js
* MIT License (c) 2014 David Leonard
* drksephy.github.io
*************************************/

//'use strict';

/**********************
* Scanner constructor *
**********************/

function Scanner(){
    this.tokens     = []
    this.curr_row   = 1
    this.curr_col   = 1
    this.curr_token = ''
    this.curr_val   = '';

}

// Adds token to list
Scanner.prototype.addToken = function(){

    if(this.curr_token){
        console.log(this.curr_token);
        console.log(this.curr_val);
        console.log(this.curr_row);
        console.log(this.curr_col);
        var token = {
            'token': this.curr_token,
            'value': this.curr_val,
            'row'  : this.curr_row,
            'col'  : this.curr_col
        };
        this.tokens.push(token);
    }

    /*
    document.getElementById('tokens').innerHTML += "
";
    document.getElementById('tokens').innerHTML += "" + token.value + "	";
    document.getElementById('tokens').innerHTML += "" + token.value + "	";
    document.getElementById('tokens').innerHTML += "" + token.row + "	";
    document.getElementById('tokens').innerHTML += "" + token.col + "	";
    document.getElementById('tokens').innerHTML += "
";
    */

    return;
}

// Resets values of token
Scanner.prototype.reset = function(){
    this.curr_val = '';
    this.curr_token = '';
    return;
}

// Default printer method
Scanner.prototype.printer = function(){
    console.log("Printer method");
    return;
}

// Retrieves value from table
Scanner.prototype.lookup = function(table, key){
    return table[key];
}

// Returns ascii value of character
Scanner.prototype.toAscii = function(char){
    return char.charCodeAt();
}

// Returns lowercase string
Scanner.prototype.toLower = function(char){
    return char.toLowerCase();
}

// Returns uppercase string
Scanner.prototype.toUpper = function(char){
    return char.toUpperCase();
}

// Handles whitespace character
Scanner.prototype.setSpace = function(ascii_value){
    console.log("SETSPACE");
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    return;
}

// Handles comments
Scanner.prototype.setComment = function(char){
    // TODO
    return;
}

// Handles numerical characters
Scanner.prototype.setDigit = function(char){
    // TODO
    return;
}

// Handles newline characters
Scanner.prototype.setLine = function(ascii_value){
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    if(ascii_value == '10' || ascii_value == '13'){
        self.curr_row += 1;
        self.curr_col = 0;
    }
    return;
}

// Adds the last token into the list, sets new token
Scanner.prototype.setToken = function(token_type, character){
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    this.curr_token = token_type;
    this.curr_val += character;
    return;
}

// Handles characters
Scanner.prototype.setCharacter = function(character){
    if(this.curr_token != 'TK_IDENTIFIER'){
        Scanner.prototype.setToken('TK_IDENTIFIER', character);
    }
    else{
        this.curr_val += character;
        if(this.curr_val in keywords){
            this.curr_token = keywords[this.curr_val];
        }
        else if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    return;
}

// Main scanner function
function scan(){
    // Get input text from textarea
    var program = document.getElementById("program").value;
    document.getElementById("demo").innerHTML = program;
    // Initalize scanner
    var scanner = new Scanner();

    // Begin scanning input text
    for(var i = 0; i < program.length; i++){
        console.log(program[i]);
        var character = scanner.toUpper(program[i]);
        var ascii = scanner.toAscii(character);
        console.log(ascii);
        console.log(scanner.curr_val);
        // Handle case for newline character
        if(ascii == '10'){
            scanner.setLine(ascii);
        }
        // Handle case for space
        else if(ascii == '32'){
            scanner.setSpace(ascii);
        }
        // Handle case for valid letters
        else if( (ascii >= 97 && ascii <= 122) || (ascii >= 65 && ascii <= 90) ){
            console.log("HELLO");
            scanner.setCharacter(character);
        }

        scanner.curr_col += 1;

    }
    console.log(scanner.tokens);

}

var keywords = {
    'BEGIN'     : 'TK_BEGIN',
    'BREAK'     : 'TK_BREAK',
    'CONST'     : 'TK_CONST',
    'DO'        : 'TK_DO',
    'DOWNTO'    : 'TK_DOWNTO',
    'ELSE'      : 'TK_ELSE',
    'END'       : 'TK_END',
    'END.'      : 'TK_END_CODE',
    'FOR'       : 'TK_FOR',
    'FUNCTION'  : 'TK_FUNCTION',
    'IDENTIFIER': 'TK_IDENTIFIER',
    'IF'        : 'TK_IF',
    'LABEL'     : 'TK_LABEL',
    'PROGRAM'   : 'TK_PROGRAM',
    'REPEAT'    : 'TK_REPEAT',
    'STRING'    : 'TK_STRING',
    'THEN'      : 'TK_THEN',
    'TO'        : 'TK_TO',
    'TYPE'      : 'TK_TYPE',
    'VAR'       : 'TK_VAR',
    'UNTIL'     : 'TK_UNTIL',
    'WHILE'     : 'TK_WHILE',
    'INTEGER'   : 'TK_ID_INTEGER',
    'REAL'      : 'TK_ID_REAL',
    'CHAR'      : 'TK_ID_CHAR',
    'BOOLEAN'   : 'TK_ID_BOOLEAN',
    'OF'        : 'TK_OF'
}

var operators = {
    '+'         : 'TK_PLUS',
    '-'         : 'TK_MINUS',
    '*'         : 'TK_MULT',
    '/'         : 'TK_DIV_FLOAT',
    'DIV'       : 'TK_DIV',
    'MOD'       : 'TK_MOD',
    ':'         : 'TK_COLON',
    '='         : 'TK_EQUALS',
    ':='        : 'TK_ASSIGNMENT',
    '>'         : 'TK_GREATER',
    '<'         : 'TK_LESS',
    '>='        : 'TK_GREATER_EQUALS',
    '<='        : 'TK_LESS_EQUALS',
    '!'         : 'TK_EXCLAMATION',
    '!='        : 'TK_NOT_EQUALS',
    'AND'       : 'TK_AND',
    'XOR'       : 'TK_XOR',
    'OR'        : 'TK_OR',
    'NOT'       : 'TK_NOT',
    ';'         : 'TK_SEMICOLON',
    '('         : 'TK_OPEN_PARENTHESIS',
    ')'         : 'TK_CLOSE_PARENTHESIS',
    '\''        : 'TK_QUOTE',
    '(*'        : 'TK_BEGIN_COMMENT',
    '*)'        : 'TK_END_COMMENT',
    ','         : 'TK_COMMA',
    '~'         : 'TK_RANGE',
    'ARRAY'     : 'TK_ARRAY',
    '['         : 'TK_OPEN_BRACKET',
    ']'         : 'TK_CLOSE_BRACKET'
}

var SYSTEM = {
    'WRITELN'   : 'TK_WRITELN',
    'ABS'       : 'TK_ABS'
}<commit_msg>scanner.js: Removing lookup method<commit_after>/************************************
* scanner.js
* MIT License (c) 2014 David Leonard
* drksephy.github.io
*************************************/

//'use strict';

/**********************
* Scanner constructor *
**********************/

function Scanner(){
    this.tokens     = []
    this.curr_row   = 1
    this.curr_col   = 1
    this.curr_token = ''
    this.curr_val   = '';

}

// Adds token to list
Scanner.prototype.addToken = function(){
    // console.log(this);
    var token = {
        'value': this.curr_val,
        'row'  : this.curr_row,
        'col'  : this.curr_col
    }

    this.tokens.push(token);

    /*
    document.getElementById('tokens').innerHTML += "
";
    document.getElementById('tokens').innerHTML += "" + token.value + "	";
    document.getElementById('tokens').innerHTML += "" + token.value + "	";
    document.getElementById('tokens').innerHTML += "" + token.row + "	";
    document.getElementById('tokens').innerHTML += "" + token.col + "	";
    document.getElementById('tokens').innerHTML += "
";
    */

    return;
}

// Resets values of token
Scanner.prototype.reset = function(){
    this.curr_val = '';
    this.curr_token = '';
    return;
}

// Default printer method
Scanner.prototype.printer = function(){
    console.log("Printer method");
    return;
}

// Returns ascii value of character
Scanner.prototype.toAscii = function(char){
    return char.charCodeAt();
}

// Returns lowercase string
Scanner.prototype.toLower = function(char){
    return char.toLowerCase();
}

// Returns uppercase string
Scanner.prototype.toUpper = function(char){
    return char.toUpperCase();
}

// Handles whitespace character
Scanner.prototype.setSpace = function(ascii_value){
    console.log("SETSPACE");
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    return;
}

// Handles comments
Scanner.prototype.setComment = function(char){
    // TODO
    return;
}

// Handles numerical characters
Scanner.prototype.setDigit = function(char){
    // TODO
    return;
}

// Handles newline characters
Scanner.prototype.setLine = function(ascii_value){
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    if(ascii_value == '10' || ascii_value == '13'){
        self.curr_row += 1;
        self.curr_col = 0;
    }
    return;
}

function setToken(token_type, character){

}
// Adds the last token into the list, sets new token
Scanner.prototype.setToken = function(token_type, character){
    console.log(this.val);
    Scanner.prototype.addToken();
    Scanner.prototype.reset();
    this.curr_token = token_type;
    this.curr_val += character;
    return;
}

// Handles characters
Scanner.prototype.setCharacter = function(character){
    if(this.curr_token != 'TK_IDENTIFIER'){
        Scanner.prototype.setToken('TK_IDENTIFIER', character);
    }
    else{
        this.curr_val += character;
        if(this.curr_val in keywords){
            this.curr_token = keywords[this.curr_val];
        }
        else if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    return;
}

// Main scanner function
function scan(){
    // Get input text from textarea
    var program = document.getElementById("program").value;
    document.getElementById("demo").innerHTML = program;
    // Initalize scanner
    var scanner = new Scanner();
    scanner.reset();
    // Begin scanning input text
    for(var i = 0; i < program.length; i++){
        var character = scanner.toUpper(program[i]);
        var ascii = scanner.toAscii(character);
        // Handle case for newline character
        if(ascii == '10'){
            scanner.setLine(ascii);
        }
        // Handle case for space
        else if(ascii == '32'){
            scanner.setSpace(ascii);
        }
        // Handle case for valid letters
        else if( (ascii >= 97 && ascii <= 122) || (ascii >= 65 && ascii <= 90) ){
            scanner.setCharacter(character);
        }

    }
    console.log(scanner.tokens);

}

var keywords = {
    'BEGIN'     : 'TK_BEGIN',
    'BREAK'     : 'TK_BREAK',
    'CONST'     : 'TK_CONST',
    'DO'        : 'TK_DO',
    'DOWNTO'    : 'TK_DOWNTO',
    'ELSE'      : 'TK_ELSE',
    'END'       : 'TK_END',
    'END.'      : 'TK_END_CODE',
    'FOR'       : 'TK_FOR',
    'FUNCTION'  : 'TK_FUNCTION',
    'IDENTIFIER': 'TK_IDENTIFIER',
    'IF'        : 'TK_IF',
    'LABEL'     : 'TK_LABEL',
    'PROGRAM'   : 'TK_PROGRAM',
    'REPEAT'    : 'TK_REPEAT',
    'STRING'    : 'TK_STRING',
    'THEN'      : 'TK_THEN',
    'TO'        : 'TK_TO',
    'TYPE'      : 'TK_TYPE',
    'VAR'       : 'TK_VAR',
    'UNTIL'     : 'TK_UNTIL',
    'WHILE'     : 'TK_WHILE',
    'INTEGER'   : 'TK_ID_INTEGER',
    'REAL'      : 'TK_ID_REAL',
    'CHAR'      : 'TK_ID_CHAR',
    'BOOLEAN'   : 'TK_ID_BOOLEAN',
    'OF'        : 'TK_OF'
}

var operators = {
    '+'         : 'TK_PLUS',
    '-'         : 'TK_MINUS',
    '*'         : 'TK_MULT',
    '/'         : 'TK_DIV_FLOAT',
    'DIV'       : 'TK_DIV',
    'MOD'       : 'TK_MOD',
    ':'         : 'TK_COLON',
    '='         : 'TK_EQUALS',
    ':='        : 'TK_ASSIGNMENT',
    '>'         : 'TK_GREATER',
    '<'         : 'TK_LESS',
    '>='        : 'TK_GREATER_EQUALS',
    '<='        : 'TK_LESS_EQUALS',
    '!'         : 'TK_EXCLAMATION',
    '!='        : 'TK_NOT_EQUALS',
    'AND'       : 'TK_AND',
    'XOR'       : 'TK_XOR',
    'OR'        : 'TK_OR',
    'NOT'       : 'TK_NOT',
    ';'         : 'TK_SEMICOLON',
    '('         : 'TK_OPEN_PARENTHESIS',
    ')'         : 'TK_CLOSE_PARENTHESIS',
    '\''        : 'TK_QUOTE',
    '(*'        : 'TK_BEGIN_COMMENT',
    '*)'        : 'TK_END_COMMENT',
    ','         : 'TK_COMMA',
    '~'         : 'TK_RANGE',
    'ARRAY'     : 'TK_ARRAY',
    '['         : 'TK_OPEN_BRACKET',
    ']'         : 'TK_CLOSE_BRACKET'
}

var SYSTEM = {
    'WRITELN'   : 'TK_WRITELN',
    'ABS'       : 'TK_ABS'
}<|endoftext|>


<commit_before>/**
 * Builds a nested accordion widget.
 *
 * Invoke on an HTML list element with the jQuery plugin pattern.
 * - For example, $('.menu').drupalNavbarMenu();
 */

(function ($, Drupal) {

"use strict";

/**
 * Store the open menu tray.
 */

  $.fn.drupalNavbarMenu = function (options) {

    // Merge options onto defaults.
    var settings = $.extend({}, {
      twisties: true,
      activeTrail: true,
      listLevels: true
    }, options);

    var ui = {
      'handleOpen': Drupal.t('Extend'),
      'handleClose': Drupal.t('Collapse')
    };
    /**
     * Handle clicks from the disclosure button on an item with sub-items.
     *
     * @param {Object} event
     *   A jQuery Event object.
     */
    function toggleClickHandler (event) {
      var $toggle = $(event.target).filter('.navbar-handle');
      if ($toggle.length) {
        var $item = $toggle.closest('li');
        // Toggle the list item.
        toggleList($item);
        // Close open sibling menus.
        var $openItems = $item.siblings().filter('.open');
        toggleList($openItems, false);
      }
    }
    /**
     * Toggle the open/close state of a list is a menu.
     *
     * @param {jQuery} $item
     *   The li item to be toggled.
     *
     * @param {Boolean} switcher
     *   A flag that forces toggleClass to add or a remove a class, rather than
     *   simply toggling its presence.
     */
    function toggleList ($item, switcher) {
      var $toggle = $item.children('.navbar-box').children('.navbar-handle');
      switcher = (typeof switcher !== 'undefined') ? switcher : !$item.hasClass('open');
      // Toggle the item open state.
      $item.toggleClass('open', switcher);
      // Twist the toggle.
      $toggle.toggleClass('open', switcher);
      // Adjust the toggle text.
      $toggle
        .find('.action')
        // Expand Structure, Collapse Structure
        .text((switcher) ?  ui.handleClose : ui.handleOpen);
    }
    /**
     * Wrap menu links is standardized markup.
     *
     * Items with sub-elements have a list toggle attached to them. Menu item
     * links and the corresponding list toggle are wrapped with in a div
     * classed with .navbar-box. The .navbar-box div provides a positioning
     * context for the item list toggle twisty.
     *
     * @param {jQuery} $menu
     *   The root of the menu to be initialized.
     */
    function processMenuLinks ($menu, settings) {
      // Initialize items and their links.
      $menu
        .find('li > a, li > span')
        .once('navbar-menu')
        .addClass('navbar-menu-item')
        .wrap('
');
        // Add a handle to each list item if it has a menu.

      if (settings.twisties) {
        var options = {
          'class': 'navbar-icon navbar-handle',
          'action': ui.handleOpen,
          'text': ''
        };
        $menu
          .find('li')
          .each(function (index, element) {
            var $item = $(element);
            var $menus = $item.children('ul.menu').once('navbar-menu');
            if ($menus.length) {
              var $box = $item.children('.navbar-box');
              options.text = Drupal.t('@label', {'@label': $box.find('a').text()});
              $item
                .addClass('navbar-twisty')
                .children('.navbar-box')
                .append(Drupal.theme('navbarMenuItemToggle', options));
            }
          });
      }
    }
    /**
     * Adds a level class to each list based on its depth in the menu.
     *
     * This function is called recursively on each sub level of lists elements
     * until the depth of the menu is exhausted.
     *
     * @param {jQuery} $lists
     *   A jQuery object of ul elements.
     *
     * @param {Integer} level
     *   The current level number to be assigned to the list elements.
     */
    function markListLevels ($lists, level) {
      level = (!level) ? 1 : level;
      $lists = $lists.children('li')
        .addClass('navbar-level-' + level)
        // Retrieve child menus.
        .children('ul');
      if ($lists.length) {
        markListLevels($lists, level + 1);
      }
    }
    /**
     * On page load, open the active menu item.
     *
     * Marks the trail of the active link in the menu back to the root of the
     * menu with .active-trail.
     *
     * @param {jQuery} $menu
     *   The root of the menu.
     */
    function openActiveItem ($menu) {
      var pathname = location.pathname;
      // Get all menu items that start with the location path.
      var $pathItem = $menu.find('a[href^="' + pathname + '"]');

      // Clear any existing menu trails.
      $menu.find('.navbar-active, .navbar-active-trail').removeClass('navbar-active navbar-active-trail');
      /**
       * Adds the navbar-active class active menu item.
       *
       * In addition a navbar-active-trail class is added to all parent menu
       * list items.
       *
       * @param jQuery $pathItem
       *   A jQuery object of the active menu item.
       */
      function markItemTrail ($pathItem) {
        $pathItem.addClass('navbar-active');
        var $activeTrail = $pathItem.parentsUntil('.navbar-root', 'li').addClass('navbar-active-trail');
        toggleList($activeTrail, true);
      }

      if ($pathItem.length) {
        // If the path yields more than one match, try to narrow the items down
        // by the params and hash.
        if ($pathItem.length > 1) {
          for (var i = 0, aspects = ['', location.search, location.hash, (location.search + location.hash)], len = aspects.length; i < len; i++) {
            $pathItem = $menu.find('a[href="' + pathname + aspects[i] + '"]');
            if ($pathItem.length === 1) {
              break;
            }
          }
        }
        if ($pathItem.length === 1) {
          markItemTrail($pathItem);
        }
      }
    }
    // Return the jQuery object.
    return this.each(function (selector) {
      var $menu = $(this);
      var rootNotProcessed = $menu.once('navbar-menu');
      if (rootNotProcessed.length) {
        $menu
          .addClass('navbar-menu-root navbar-root')
          .on('click.navbar', toggleClickHandler);
      }
      // Process components of the menu.
      processMenuLinks($menu, settings);
      // Add a menu level class to each menu item.
      if (settings.listLevels) {
        markListLevels($menu);
      }
      // Restore previous and active states.
      if (settings.activeTrail) {
        openActiveItem($menu);
      }
    });
  };

  /**
   * A toggle is an interactive element often bound to a click handler.
   *
   * @return {String}
   *   A string representing a DOM fragment.
   */
  Drupal.theme.navbarMenuItemToggle = function (options) {
    return '<button class="' + options['class'] + '">' + options.action + '' + options.text + '</button>';
  };

}(jQuery, Drupal));
<commit_msg>Allow for a wrapper element around the menu item just inside an li element.<commit_after>/**
 * Builds a nested accordion widget.
 *
 * Invoke on an HTML list element with the jQuery plugin pattern.
 * - For example, $('.menu').drupalNavbarMenu();
 */

(function ($, Drupal) {

"use strict";

/**
 * Store the open menu tray.
 */

  $.fn.drupalNavbarMenu = function (options) {

    // Merge options onto defaults.
    var settings = $.extend({}, {
      twisties: true,
      activeTrail: true,
      listLevels: true
    }, options);

    var ui = {
      'handleOpen': Drupal.t('Extend'),
      'handleClose': Drupal.t('Collapse')
    };
    /**
     * Handle clicks from the disclosure button on an item with sub-items.
     *
     * @param {Object} event
     *   A jQuery Event object.
     */
    function toggleClickHandler (event) {
      var $toggle = $(event.target).filter('.navbar-handle');
      if ($toggle.length) {
        var $item = $toggle.closest('li');
        // Toggle the list item.
        toggleList($item);
        // Close open sibling menus.
        var $openItems = $item.siblings().filter('.open');
        toggleList($openItems, false);
      }
    }
    /**
     * Toggle the open/close state of a list is a menu.
     *
     * @param {jQuery} $item
     *   The li item to be toggled.
     *
     * @param {Boolean} switcher
     *   A flag that forces toggleClass to add or a remove a class, rather than
     *   simply toggling its presence.
     */
    function toggleList ($item, switcher) {
      var $toggle = $item.children('.navbar-box').children('.navbar-handle');
      switcher = (typeof switcher !== 'undefined') ? switcher : !$item.hasClass('open');
      // Toggle the item open state.
      $item.toggleClass('open', switcher);
      // Twist the toggle.
      $toggle.toggleClass('open', switcher);
      // Adjust the toggle text.
      $toggle
        .find('.action')
        // Expand Structure, Collapse Structure
        .text((switcher) ?  ui.handleClose : ui.handleOpen);
    }
    /**
     * Wrap menu links is standardized markup.
     *
     * Items with sub-elements have a list toggle attached to them. Menu item
     * links and the corresponding list toggle are wrapped with in a div
     * classed with .navbar-box. The .navbar-box div provides a positioning
     * context for the item list toggle twisty.
     *
     * @param {jQuery} $menu
     *   The root of the menu to be initialized.
     */
    function processMenuLinks ($menu, settings) {
      // Initialize items and their links.
      $menu
        // Allow for a wrapper just inside the menu item li.
        .find('li > a, li > span, li > * > a, li > * > span')
        .once('navbar-menu')
        .addClass('navbar-menu-item')
        .wrap('
');
        // Add a handle to each list item if it has a menu.

      if (settings.twisties) {
        var options = {
          'class': 'navbar-icon navbar-handle',
          'action': ui.handleOpen,
          'text': ''
        };
        $menu
          .find('li')
          .each(function (index, element) {
            var $item = $(element);
            var $menus = $item.children('ul.menu').once('navbar-menu');
            if ($menus.length) {
              var $box = $item.children('.navbar-box');
              options.text = Drupal.t('@label', {'@label': $box.find('a').text()});
              $item
                .addClass('navbar-twisty')
                .children('.navbar-box')
                .append(Drupal.theme('navbarMenuItemToggle', options));
            }
          });
      }
    }
    /**
     * Adds a level class to each list based on its depth in the menu.
     *
     * This function is called recursively on each sub level of lists elements
     * until the depth of the menu is exhausted.
     *
     * @param {jQuery} $lists
     *   A jQuery object of ul elements.
     *
     * @param {Integer} level
     *   The current level number to be assigned to the list elements.
     */
    function markListLevels ($lists, level) {
      level = (!level) ? 1 : level;
      $lists = $lists.children('li')
        .addClass('navbar-level-' + level)
        // Retrieve child menus.
        .children('ul');
      if ($lists.length) {
        markListLevels($lists, level + 1);
      }
    }
    /**
     * On page load, open the active menu item.
     *
     * Marks the trail of the active link in the menu back to the root of the
     * menu with .active-trail.
     *
     * @param {jQuery} $menu
     *   The root of the menu.
     */
    function openActiveItem ($menu) {
      var pathname = location.pathname;
      // Get all menu items that start with the location path.
      var $pathItem = $menu.find('a[href^="' + pathname + '"]');

      // Clear any existing menu trails.
      $menu.find('.navbar-active, .navbar-active-trail').removeClass('navbar-active navbar-active-trail');
      /**
       * Adds the navbar-active class active menu item.
       *
       * In addition a navbar-active-trail class is added to all parent menu
       * list items.
       *
       * @param jQuery $pathItem
       *   A jQuery object of the active menu item.
       */
      function markItemTrail ($pathItem) {
        $pathItem.addClass('navbar-active');
        var $activeTrail = $pathItem.parentsUntil('.navbar-root', 'li').addClass('navbar-active-trail');
        toggleList($activeTrail, true);
      }

      if ($pathItem.length) {
        // If the path yields more than one match, try to narrow the items down
        // by the params and hash.
        if ($pathItem.length > 1) {
          for (var i = 0, aspects = ['', location.search, location.hash, (location.search + location.hash)], len = aspects.length; i < len; i++) {
            $pathItem = $menu.find('a[href="' + pathname + aspects[i] + '"]');
            if ($pathItem.length === 1) {
              break;
            }
          }
        }
        if ($pathItem.length === 1) {
          markItemTrail($pathItem);
        }
      }
    }
    // Return the jQuery object.
    return this.each(function (selector) {
      var $menu = $(this);
      var rootNotProcessed = $menu.once('navbar-menu');
      if (rootNotProcessed.length) {
        $menu
          .addClass('navbar-menu-root navbar-root')
          .on('click.navbar', toggleClickHandler);
      }
      // Process components of the menu.
      processMenuLinks($menu, settings);
      // Add a menu level class to each menu item.
      if (settings.listLevels) {
        markListLevels($menu);
      }
      // Restore previous and active states.
      if (settings.activeTrail) {
        openActiveItem($menu);
      }
    });
  };

  /**
   * A toggle is an interactive element often bound to a click handler.
   *
   * @return {String}
   *   A string representing a DOM fragment.
   */
  Drupal.theme.navbarMenuItemToggle = function (options) {
    return '<button class="' + options['class'] + '">' + options.action + '' + options.text + '</button>';
  };

}(jQuery, Drupal));
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('parallax-content', 'Integration | Component | parallax content', {
  integration: true
});

test('it renders', function(assert) {
  // Template block usage:
  this.render(hbs`
    {{#parallax-content}}
      template block text
    {{/parallax-content}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');
});

test('offsetTop is handled properly', function(assert) {
  // Template block usage:
  this.set('top', 120);

  this.render(hbs`
    {{#parallax-content speed=0.3 offsetTop=top}}
      template block text
    {{/parallax-content}}
  `);

  assert.equal(this.$('.parallax-content').css('position'), 'absolute');
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), '120px');
  this.set('top', -50);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), '-50px');
});

test('scrolling is handled properly', function(assert) {
  // Template block usage:
  // let done = assert.async();

  this.set('windoc', {
    scrollTop: 0
  });

  this.render(hbs`

    {{#parallax-content speed=-0.5 windoc=windoc}}
      template block text
    {{/parallax-content}}

  `);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), '0px');
  this.set('windoc.scrollTop', 400);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), '200px');

});
<commit_msg>Phantomjs hack<commit_after>/*global PluginArray:true*/
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('parallax-content', 'Integration | Component | parallax content', {
  integration: true
});

const IS_PHANTOM = !(window.navigator.plugins instanceof PluginArray) ||
  window.navigator.plugins.length === 0;

test('it renders', function(assert) {
  // Template block usage:
  this.render(hbs`
    {{#parallax-content}}
      template block text
    {{/parallax-content}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');
});

test('offsetTop is handled properly', function(assert) {
  // Template block usage:
  this.set('top', 120);

  this.render(hbs`
    {{#parallax-content speed=0.3 offsetTop=top}}
      template block text
    {{/parallax-content}}
  `);

  assert.equal(this.$('.parallax-content').css('position'), 'absolute');
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), IS_PHANTOM ? '60px' : '120px');
  this.set('top', -50);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), IS_PHANTOM ? '-25px' : '-50px');
});

test('scrolling is handled properly', function(assert) {
  // Template block usage:
  // let done = assert.async();

  this.set('windoc', {
    scrollTop: 0
  });

  this.render(hbs`

    {{#parallax-content speed=-0.5 windoc=windoc}}
      template block text
    {{/parallax-content}}

  `);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), '0px');
  this.set('windoc.scrollTop', 400);
  assert.equal(this.$('.parallax-content .scroll-speed-adjust').css('top'), IS_PHANTOM ? '100px' : '200px');

});
<|endoftext|>


<commit_before>/************************************
* scanner.js
* MIT License (c) 2014 David Leonard
* drksephy.github.io
*************************************/

'use strict';

/**********************
* Scanner constructor *
**********************/

function Scanner(){
    this.tokens     = [];
    this.curr_row   = 1 ;
    this.curr_col   = 1 ;
    this.curr_token = '';
    this.curr_val   = '';
    this.strings    = false;

}

// Adds token to list
Scanner.prototype.addToken = function(){

    if(this.curr_token){
        var token = {
            'token': this.curr_token,
            'value': this.curr_val,
            'row'  : this.curr_row,
            'col'  : this.curr_col
        }
        this.tokens.push(token);

        // TODO: Use bootstrap to render these tables
        var table = document.getElementById('list');
        var node = document.createElement('tr');
        for(var prop in token){
            table.appendChild(node);
            var entry = node.appendChild(document.createElement('td'));
            entry.appendChild(document.createTextNode(token[prop]));
        }
    }

    return;
}

// Resets values of token
Scanner.prototype.reset = function(){
    this.curr_val = '';
    this.curr_token = '';
    return;
}

// Returns ascii value of character
Scanner.prototype.toAscii = function(character){
    return character.charCodeAt();
}

// Returns lowercase string
Scanner.prototype.toLower = function(character){
    return character.toLowerCase();
}

// Returns uppercase string
Scanner.prototype.toUpper = function(character){
    return character.toUpperCase();
}

// Handles comments
Scanner.prototype.setComment = function(character){
    // TODO
    return;
}

// Handles EOF
Scanner.prototype.setEOF = function(character){
    this.curr_val = 'TK_EOF';
    this.curr_val = 'EOF';
    this.addToken();
    return;
}

// Handles numerical characters
Scanner.prototype.setDigit = function(character){
    if(this.curr_token === 'TK_REAL' || this.curr_token === 'TK_INT'){
        this.curr_val += character;
    }
    else{
        this.setToken('TK_INT', character);
    }
    return;
}

// Handles strings, builds string up
Scanner.prototype.setString = function(character){
    this.curr_val += character;
    if((this.curr_token === 'TK_SINGLE_QUOTE' && character === "'") ||
       (this.curr_token === 'TK_DOUBLE_QUOTE' && character === '"')){
        this.buildString();
    }
    return;
}

// Builds final string token
Scanner.prototype.buildString = function(){
    this.curr_token = 'TK_STRING';
    this.addToken();
    this.reset();
    this.strings = false;
}

// Handles newline characters
Scanner.prototype.setLine = function(ascii_value){
    this.addToken();
    this.reset();
    if(ascii_value === 10){
        this.curr_row += 1;
        this.curr_col = 0;
    }
    return;
}

// Handles whitespace character
Scanner.prototype.setSpace = function(ascii_value){
    this.addToken();
    this.reset();
    return;
}

// Adds the last token into the list, sets new token
Scanner.prototype.setToken = function(token_type, character){
    this.addToken();
    this.reset();
    this.curr_token = token_type;
    this.curr_val += character;
    return;
}

// Handles characters
Scanner.prototype.setCharacter = function(character){
    if(this.curr_token != 'TK_IDENTIFIER'){
        this.setToken('TK_IDENTIFIER', character);
    }
    else{
        this.curr_val += character;
        if(this.curr_val in keywords){
            this.curr_token = keywords[this.curr_val];
        }
        else if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    return;
}

// Handles operators
Scanner.prototype.setOperator = function(character){
    if(character === '.' && this.curr_token === 'TK_INT'){
        this.curr_token = 'TK_REAL';
        this.curr_val += character;
    }

    else if(this.curr_val + character in operators){
        this.curr_val += character;
        // Handle all two-symbol operators
        if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    else{
        this.setToken(operators[character], character);
    }
    return;
}

// Main scanner function
function scan(){

    // Get input text from textarea
    var program = document.getElementById("program").value;
    document.getElementById("demo").innerHTML = program;

    // Initalize scanner
    var scanner = new Scanner();

    // Begin scanning input text
    for(var i = 0; i < program.length; i++){

        // Handle case when we close the string
        if(scanner.curr_token === 'TK_SINGLE_QUOTE' || scanner.curr_token === 'TK_DOUBLE_QUOTE'){
            scanner.setString(program[i]);
        }

        if(!scanner.strings){
            // If we are not generating a string, do this
            var character = scanner.toUpper(program[i]);
            var ascii = scanner.toAscii(character);
            // Handle case for newline character
            if(ascii == '10'){
                scanner.setLine(ascii);
            }

            // Handle case for space
            else if(ascii == '32'){
                scanner.setSpace(ascii);
            }

            // Handle case for valid letters
            else if( (ascii >= 97 && ascii <= 122) || (ascii >= 65 && ascii <= 90) ){
                scanner.setCharacter(character);
            }

            // Handle case for numbers
            else if(ascii >= 48 && ascii <= 57){
                scanner.setDigit(character);
            }

            // Handle case for strings composed with single quote
            else if(ascii === 39){
                scanner.setToken('TK_SINGLE_QUOTE', character);
                scanner.strings = true;
            }

            // Handle case for strings composed with double quotes
            else if(ascii === 34){
                scanner.setToken('TK_DOUBLE_QUOTE', character);
                scanner.strings = true;
            }

            // Handle case for operators
            else if(character in operators){
                scanner.setOperator(character);
            }
        }
        scanner.curr_col += 1;
    }

    //scanner.setEOF();
    console.log(scanner.tokens);

}

var keywords = {
    'begin'     : 'TK_BEGIN',
    'break'     : 'TK_BREAK',
    'const'     : 'TK_CONST',
    'do'        : 'TK_DO',
    'downto'    : 'TK_DOWNTO',
    'else'      : 'TK_ELSE',
    'end'       : 'TK_END',
    'end.'      : 'TK_END_CODE',
    'for'       : 'TK_FOR',
    'function'  : 'TK_FUNCTION',
    'identifier': 'TK_IDENTIFIER',
    'if'        : 'TK_IF',
    'label'     : 'TK_LABEL',
    'program'   : 'TK_PROGRAM',
    'repeat'    : 'TK_REPEAT',
    'string'    : 'TK_STRING',
    'then'      : 'TK_THEN',
    'to'        : 'TK_TO',
    'type'      : 'TK_TYPE',
    'var'       : 'TK_VAR',
    'until'     : 'TK_UNTIL',
    'while'     : 'TK_WHILE',
    'integer'   : 'TK_ID_INTEGER',
    'real'      : 'TK_ID_REAL',
    'char'      : 'TK_ID_CHAR',
    'boolean'   : 'TK_ID_BOOLEAN',
    'of'        : 'TK_OF'
}

var operators = {
    '+'         : 'TK_PLUS',
    '-'         : 'TK_MINUS',
    '*'         : 'TK_MULT',
    '/'         : 'TK_DIV_FLOAT',
    'div'       : 'TK_DIV',
    'mod'       : 'TK_MOD',
    ':'         : 'TK_COLON',
    '='         : 'TK_EQUALS',
    ':='        : 'TK_ASSIGNMENT',
    '>'         : 'TK_GREATER',
    '<'         : 'TK_LESS',
    '.'         : 'TK_DOT',
    '>='        : 'TK_GREATER_EQUALS',
    '<='        : 'TK_LESS_EQUALS',
    '!'         : 'TK_EXCLAMATION',
    '!='        : 'TK_NOT_EQUALS',
    'and'       : 'TK_AND',
    'xor'       : 'TK_XOR',
    'or'        : 'TK_OR',
    'not'       : 'TK_NOT',
    ';'         : 'TK_SEMICOLON',
    '('         : 'TK_OPEN_PARENTHESIS',
    ')'         : 'TK_CLOSE_PARENTHESIS',
    '\''        : 'TK_SINGLE_QUOTE',
    '"'         : 'TK_DOUBLE_QUOTE',
    '(*'        : 'TK_BEGIN_COMMENT',
    '*)'        : 'TK_END_COMMENT',
    ','         : 'TK_COMMA',
    '~'         : 'TK_RANGE',
    'array'     : 'TK_ARRAY',
    '['         : 'TK_OPEN_BRACKET',
    ']'         : 'TK_CLOSE_BRACKET'
}

var SYSTEM = {
    'writeln'   : 'TK_WRITELN',
    'abs'       : 'TK_ABS'
}<commit_msg>scanner.js: Adding console logs for debugging purposes<commit_after>/************************************
* scanner.js
* MIT License (c) 2014 David Leonard
* drksephy.github.io
*************************************/

'use strict';

/**********************
* Scanner constructor *
**********************/

function Scanner(){
    this.tokens     = [];
    this.curr_row   = 1 ;
    this.curr_col   = 1 ;
    this.curr_token = '';
    this.curr_val   = '';
    this.strings    = false;

}

// Adds token to list
Scanner.prototype.addToken = function(){

    if(this.curr_token){
        var token = {
            'token': this.curr_token,
            'value': this.curr_val,
            'row'  : this.curr_row,
            'col'  : this.curr_col
        }
        this.tokens.push(token);

        // TODO: Use bootstrap to render these tables
        var table = document.getElementById('list');
        var node = document.createElement('tr');
        for(var prop in token){
            table.appendChild(node);
            var entry = node.appendChild(document.createElement('td'));
            entry.appendChild(document.createTextNode(token[prop]));
        }
    }

    return;
}

// Resets values of token
Scanner.prototype.reset = function(){
    this.curr_val = '';
    this.curr_token = '';
    return;
}

// Returns ascii value of character
Scanner.prototype.toAscii = function(character){
    return character.charCodeAt();
}

// Returns lowercase string
Scanner.prototype.toLower = function(character){
    return character.toLowerCase();
}

// Returns uppercase string
Scanner.prototype.toUpper = function(character){
    return character.toUpperCase();
}

// Handles comments
Scanner.prototype.setComment = function(character){
    // TODO
    return;
}

// Handles EOF
Scanner.prototype.setEOF = function(character){
    this.curr_val = 'TK_EOF';
    this.curr_val = 'EOF';
    this.addToken();
    return;
}

// Handles numerical characters
Scanner.prototype.setDigit = function(character){
    if(this.curr_token === 'TK_REAL' || this.curr_token === 'TK_INT'){
        this.curr_val += character;
    }
    else{
        this.setToken('TK_INT', character);
    }
    return;
}

// Handles strings, builds string up
Scanner.prototype.setString = function(character){
    this.curr_val += character;
    console.log(character);
    if((this.curr_token === 'TK_SINGLE_QUOTE' && character === "'") ||
       (this.curr_token === 'TK_DOUBLE_QUOTE' && character === '"')){
        console.log(this.strings);
        this.strings = false;
        this.buildString();
    }
    return;
}

// Builds final string token
Scanner.prototype.buildString = function(){
    console.log("BUILDING STRING" + this.curr_val);
    this.curr_token = 'TK_STRING';
    this.addToken();
    this.reset();
    return;
}

// Handles newline characters
Scanner.prototype.setLine = function(ascii_value){
    this.addToken();
    this.reset();
    if(ascii_value === 10){
        this.curr_row += 1;
        this.curr_col = 0;
    }
    return;
}

// Handles whitespace character
Scanner.prototype.setSpace = function(ascii_value){
    this.addToken();
    this.reset();
    return;
}

// Adds the last token into the list, sets new token
Scanner.prototype.setToken = function(token_type, character){
    this.addToken();
    this.reset();
    this.curr_token = token_type;
    this.curr_val += character;
    return;
}

// Handles characters
Scanner.prototype.setCharacter = function(character){
    if(this.curr_token != 'TK_IDENTIFIER'){
        this.setToken('TK_IDENTIFIER', character);
    }
    else{
        this.curr_val += character;
        if(this.curr_val in keywords){
            this.curr_token = keywords[this.curr_val];
        }
        else if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    return;
}

// Handles operators
Scanner.prototype.setOperator = function(character){
    if(character === '.' && this.curr_token === 'TK_INT'){
        this.curr_token = 'TK_REAL';
        this.curr_val += character;
    }

    else if(this.curr_val + character in operators){
        this.curr_val += character;
        // Handle all two-symbol operators
        if(this.curr_val in operators){
            this.curr_token = operators[this.curr_val];
        }
    }
    else{
        this.setToken(operators[character], character);
    }
    return;
}

// Main scanner function
function scan(){

    // Get input text from textarea
    var program = document.getElementById("program").value;
    document.getElementById("demo").innerHTML = program;

    // Initalize scanner
    var scanner = new Scanner();

    // Begin scanning input text
    for(var i = 0; i < program.length; i++){
        //console.log(scanner.curr_token);
        // Handle case when we close the string
        if(scanner.curr_token === 'TK_SINGLE_QUOTE' || scanner.curr_token === 'TK_DOUBLE_QUOTE'){
            scanner.setString(program[i]);
        }

        if(!scanner.strings){
            console.log("doing stuff " + ": " + program[i] )
            // If we are not generating a string, do this
            var character = scanner.toUpper(program[i]);
            var ascii = scanner.toAscii(character);
            // Handle case for newline character
            if(ascii == '10'){
                scanner.setLine(ascii);
            }

            // Handle case for space
            else if(ascii == '32'){
                scanner.setSpace(ascii);
            }

            // Handle case for valid letters
            else if( (ascii >= 97 && ascii <= 122) || (ascii >= 65 && ascii <= 90) ){
                scanner.setCharacter(character);
            }

            // Handle case for numbers
            else if(ascii >= 48 && ascii <= 57){
                scanner.setDigit(character);
            }

            // Handle case for strings composed with single quote
            else if(ascii === 39){
                scanner.setToken('TK_SINGLE_QUOTE', character);
                scanner.strings = true;
            }

            // Handle case for strings composed with double quotes
            else if(ascii === 34){
                scanner.setToken('TK_DOUBLE_QUOTE', character);
                scanner.strings = true;
            }

            // Handle case for operators
            else if(character in operators){
                scanner.setOperator(character);
            }
        }
        scanner.curr_col += 1;
    }

    //scanner.setEOF();
    console.log(scanner.tokens);

}

var keywords = {
    'begin'     : 'TK_BEGIN',
    'break'     : 'TK_BREAK',
    'const'     : 'TK_CONST',
    'do'        : 'TK_DO',
    'downto'    : 'TK_DOWNTO',
    'else'      : 'TK_ELSE',
    'end'       : 'TK_END',
    'end.'      : 'TK_END_CODE',
    'for'       : 'TK_FOR',
    'function'  : 'TK_FUNCTION',
    'identifier': 'TK_IDENTIFIER',
    'if'        : 'TK_IF',
    'label'     : 'TK_LABEL',
    'program'   : 'TK_PROGRAM',
    'repeat'    : 'TK_REPEAT',
    'string'    : 'TK_STRING',
    'then'      : 'TK_THEN',
    'to'        : 'TK_TO',
    'type'      : 'TK_TYPE',
    'var'       : 'TK_VAR',
    'until'     : 'TK_UNTIL',
    'while'     : 'TK_WHILE',
    'integer'   : 'TK_ID_INTEGER',
    'real'      : 'TK_ID_REAL',
    'char'      : 'TK_ID_CHAR',
    'boolean'   : 'TK_ID_BOOLEAN',
    'of'        : 'TK_OF'
}

var operators = {
    '+'         : 'TK_PLUS',
    '-'         : 'TK_MINUS',
    '*'         : 'TK_MULT',
    '/'         : 'TK_DIV_FLOAT',
    'div'       : 'TK_DIV',
    'mod'       : 'TK_MOD',
    ':'         : 'TK_COLON',
    '='         : 'TK_EQUALS',
    ':='        : 'TK_ASSIGNMENT',
    '>'         : 'TK_GREATER',
    '<'         : 'TK_LESS',
    '.'         : 'TK_DOT',
    '>='        : 'TK_GREATER_EQUALS',
    '<='        : 'TK_LESS_EQUALS',
    '!'         : 'TK_EXCLAMATION',
    '!='        : 'TK_NOT_EQUALS',
    'and'       : 'TK_AND',
    'xor'       : 'TK_XOR',
    'or'        : 'TK_OR',
    'not'       : 'TK_NOT',
    ';'         : 'TK_SEMICOLON',
    '('         : 'TK_OPEN_PARENTHESIS',
    ')'         : 'TK_CLOSE_PARENTHESIS',
    '\''        : 'TK_SINGLE_QUOTE',
    '"'         : 'TK_DOUBLE_QUOTE',
    '(*'        : 'TK_BEGIN_COMMENT',
    '*)'        : 'TK_END_COMMENT',
    ','         : 'TK_COMMA',
    '~'         : 'TK_RANGE',
    'array'     : 'TK_ARRAY',
    '['         : 'TK_OPEN_BRACKET',
    ']'         : 'TK_CLOSE_BRACKET'
}

var SYSTEM = {
    'writeln'   : 'TK_WRITELN',
    'abs'       : 'TK_ABS'
}<|endoftext|>


<commit_before>var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// this will center the ball horizontally since half of the width of the canvas is right in the middle
var x = canvas.width/2;
// vertically, we will push the ball up 30px from the bottom of the page
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
// starting width and height
var paddleHeight = 10;
var paddleWidth = 75;
// starting x position on canvas
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, ballRadius, 0, Math.PI*2);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

function drawPaddle() {
  ctx.beginPath();
  ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

function draw() {
  // clears the canvas before ball is drawn
  ctx.clearRect(0,0, canvas.width, canvas.height);
  // adds 2 on every frame every 10 milliseconds

  //cleaned up function by calling the drawBall function each time
  drawBall();

// is y position + the position of dy (2 in this case) is less than 0
  // if it's less than 0, we know the ball is moving up and off the canvas
  if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
    dy = -dy;
  }
  if(x + dx > canvas.width-ballRadius|| x + dx < ballRadius) {
    dx = -dx;
  }

  x += dx;
  y += dy;
}

//first parameter is function to be executed
//second parameter indicates number of milliseconds before execution
setInterval(draw, 10);
<commit_msg>added event listeners and functions for key press and release<commit_after>var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// this will center the ball horizontally since half of the width of the canvas is right in the middle
var x = canvas.width/2;
// vertically, we will push the ball up 30px from the bottom of the page
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
// starting width and height
var paddleHeight = 10;
var paddleWidth = 75;
// starting x position on canvas
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;

//event listeners that will tell when a key is pressed down/when it is released
document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keyup", keyUpHandler);

// when you press the key down, it stores a keycode for the key that is pressed
  // is then passed as an argument into this function
  // keycode 39 corresponds to the right arrow
function keyDownHandler(e) {
  if(e.keycode == 39) {
    rightPressed = true;
  }
  else if (e.keyCode == 37) {
    leftPressed = true;
  }
}

function keyUpHandler(e) {
  if(e.keycode == 39) {
    rightPressed = false;
  }
  else if (e.keyCode == 37) {
    leftPressed = false;
  }
}

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, ballRadius, 0, Math.PI*2);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

function drawPaddle() {
  ctx.beginPath();
  ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

function draw() {
  // clears the canvas before ball is drawn
  ctx.clearRect(0,0, canvas.width, canvas.height);
  // adds 2 on every frame every 10 milliseconds

  //cleaned up function by calling the drawBall function each time
  drawBall();

// is y position + the position of dy (2 in this case) is less than 0
  // if it's less than 0, we know the ball is moving up and off the canvas
  if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
    dy = -dy;
  }
  if(x + dx > canvas.width-ballRadius|| x + dx < ballRadius) {
    dx = -dx;
  }

  x += dx;
  y += dy;
}

//first parameter is function to be executed
//second parameter indicates number of milliseconds before execution
setInterval(draw, 10);
<|endoftext|>


<commit_before>const $$ = function(aObj) {
	const _r = {
		/**
		 * <odoc>
		 * <key>$$(aObject).get(aPath) : Object</key>
		 * Given aObject it will try to parse the aPath a retrive the corresponding object under that path. Example:\
		 * \
		 * var a = { a : 1, b : { c: 2, d: [0, 1] } };\
		 * \
		 * print($$(a).get("b.c")); // 2\
		 * sprint($$(a).get("b.d")); // [0, 1]\
		 * print($$(a).get("b.d[0]")); // 0\
		 * \
		 * </odoc>
		 */
		get: (aPath) => {
			if (!isObject(aObj)) return void 0;

			aPath = aPath.replace(/\[(\w+)\]/g, '.$1');
			aPath = aPath.replace(/^\./, '');

			var a = aPath.split('.');
			for (var i = 0, n = a.length; i < n; ++i) {
				var k = a[i];
				if (k in aObj) {
					aObj = aObj[k];
				} else {
					return;
				}
			}
			return aObj;
		},
		/**
		 * <odoc>
		 * <key>$$(aObject).set(aPath, aNewValue) : Object</key>
		 * Given aObject it will try to parse the aPath a set the corresponding object under that path to aNewValue. Example:\
		 * \
		 * var a = { a : 1, b : { c: 2, d: [0, 1] } };\
		 * \
		 * sprint($$(a).set("b.c", 123); // { a : 1, b : { c: 123, d: [0, 1] } }\
		 * \
		 * </odoc>
		 */
		set: (aPath, aNewValue) => {
			if (!isObject(aObj)) return void 0;
			var orig = aObj;

			aPath = aPath.replace(/\[(\w+)\]/g, '.$1');
			aPath = aPath.replace(/^\./, '');

			var a = aPath.split('.');
			var prev, prevK;
			for (var i = 0, n = a.length; i < n; ++i) {
				var k = a[i];
				prev = aObj;
				prevK = k;
				if (k in aObj) {
					aObj = aObj[k];
				} else {
					aObj[k] = {};
					aObj = aObj[k];
				}
			}
			prev[prevK] = aValue;
			return orig;
        },
        isDef: () => { return (!(typeof aObj == 'undefined')) ? true : false; },
        isUnDef: () => { return (typeof aObj == 'undefined') ? true : false; },
        isArray: () => { return Array.isArray(aObj); },
        isMap: () => { return (Object.prototype.toString.call(aObj) == "[object Object]"); },
        isObject: () => { var type = typeof aObj; return type === 'function' || type === 'object' && !!aObj; },
        isFunction: () => { return typeof aObj == 'function' || false; },
        isString: () => { return typeof aObj == 'string' || false; },
        isNumber: () => { return !isNaN(parseFloat(aObj)) && isFinite(aObj); },
        isDate: () => { return (null != aObj) && !isNaN(aObj) && ("undefined" !== typeof aObj.getDate); }
	};
	return _r;
};

const _$ = function(aValue, aPrefixMessage) {
    var defined;
    if ($$(aPrefixMessage).isDef()) aPrefixMessage += " "; else aPrefixMessage = "";
    if ($$(aValue).isDef()) defined = true; else defined = false;

    const __r = {
		// Defaults
        default : (aVal) => {
            if (!defined) return aVal; else return aValue;
        },
        $_ : (aMessage) => {
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "not available";
			if (!defined) throw aMessage;
			return aValue;
		},

		// Type check
        isNumber: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a number";
            if (defined && !$$(aValue).isNumber()) throw aMessage;
            return __r;
        },
        isString: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a string";
            if (defined && !$$(aValue).isString()) throw aMessage;
            return __r;
        },
        isBoolean: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not boolean";
            if (defined && (typeof aValue !== "boolean")) throw aMessage;
            return __r;
        },
        isArray: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not an array";
            if (defined && !$$(aValue).isArray()) throw aMessage;
            return __r;
        },
        isMap: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a map";
            if (defined && !$$(aValue).isMap()) throw aMessage;
            return __r;
		},
		isJavaObject: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a java object";
            if (defined && !isJavaObject(aValue)) throw aMessage;
            return __r;
		},
		isInstanceOf: (aClass, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not an instance of " + aClass;
            if (defined && !(aValue instanceof aClass)) throw aMessage;
            return __r;
		},

		// Generic validations
        check: (aFunction, aMessage) => {
			if (!$$(aFunction).isFunction() && !$$(aFunction).isString()) throw "please provide a function to check";
            var res = ($$(aValue).isFunction() ? aFunction(aValue) : (new Function('v', 'return ' + aFunction))(aValue));
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not ok";
            if (defined && !res) throw aMessage;
            return __r;
        },
        expr: (aEval, aMessage) => {
			if (!$$(aEval).isString()) throw "please provide an expression";
            var res = af.eval(templify(aEval, { v: aValue }));
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not ok";
            if (defined && !res) throw aMessage;
            return __r;
		},
		equals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is equals to " + aVal;
            if (defined && aValue == aVal) throw aMessage;
            return __r;
        }        ,
        notEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not equals to " + aVal;
            if (defined && aValue != aVal) throw aMessage;
            return __r;
		},
		anyOf: (aVals, aMessage) => {
			if (!$$(aVals).isArray()) throw "please provide an array of values";
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "has a value not in " + JSON.stringify(aVals);
			if (defined && $$(aValue).isArray()) {
				aValue.forEach((v) => {
					if (aVals.indexOf(v) < 0) throw aMessage;
				});
            }
            return __r;
		},
		oneOf: (aVals, aMessage) => {
			if (!$$(aVals).isArray()) throw "please provide an array of values";
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not one of " + JSON.stringify(aVals);
            if (defined && !$$(aValue).isArray() && aVals.indexOf(aValue) < 0) throw aMessage;
            return __r;
		},

		// Numeric validations
        between: (aValA, aValB, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not between " + aValA + " and " + aValB;
            if (defined && (aValue < aValB && aValue > aValA)) throw aMessage;
        },
        betweenEquals: (aValA, aValB, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not between " + aValA + " and " + aValB;
            if (defined && (aValue <= aValB && aValue >= aValA)) throw aMessage;
        },
        less: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is less than " + aVal;
            if (defined && aValue > aVal) throw aMessage;
            return __r;
        },
        lessEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is less or equals than " + aVal;
            if (defined && aValue >= aVal) throw aMessage;
            return __r;
        },
        greater: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is greater than " + aVal;
            if (defined && aValue < aVal) throw aMessage;
            return __r;
        },
        greaterEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is greater or equals than " + aVal;
            if (defined && aValue <= aVal) throw aMessage;
            return __r;
        },

		// String validations
        notEmpty: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is empty";
            if (defined && String(aValue) == "") throw aMessage;
            return __r;
        },
        empty: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not empty";
            if (defined && String(aValue) != "") throw aMessage;
            return __r;
        },
        contains: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if contains";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't contain " + aVal;
            if (defined && String(aValue).indexOf(aVal) < 0) throw aMessage;
            return __r;
        },
        notContains: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if not contains";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "contains " + aVal;
            if (defined && String(aValue).indexOf(aVal) >= 0) throw aMessage;
            return __r;
        },
        starts: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it starts with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't start with '" + aVal + "'";
            if (defined && !(aValue.startsWith(aValu))) throw aMessage;
            return __r;
        },
        ends: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it ends with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't end with '" + aVal + "'";
            if (defined && !(aValue.endsWith(aVal))) throw aMessage;
            return __r;
        },
        notStarts: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it not starts with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "starts with '" + aVal + "'";
            if (defined && (aValue.startsWith(aValu))) throw aMessage;
            return __r;
        },
        notEnds: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it not ends with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "ends with '" + aVal + "'";
            if (defined && (aValue.endsWith(aVal))) throw aMessage;
            return __r;
        },
        regexp: (aRegExp, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't match '" + aRegExp + "'";
            if (!(aRegExp instanceof RegExp)) throw "is not a regular expression (" + aRegExp + ")";
            if (defined && !aRegExp.test(aValue)) throw aMessage;
            return __r;
        },
        javaRegexp: (aRegExp, aMods, aMessage) => {
			if ($$(aRegExp).isUnDef() || !$$(aRegExp).isString()) throw "please provide a regular expression string";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't match '" + aRegExp + "'";
            if (defined && !javaRegExp(aValue).test(aRegExp, aMods)) throw aMessage;
            return __r;
        }
    };
    return __r;
};
<commit_msg>openafsigil: small bug corrections<commit_after>const $$ = function(aObj) {
	const _r = {
		/**
		 * <odoc>
		 * <key>$$(aObject).get(aPath) : Object</key>
		 * Given aObject it will try to parse the aPath a retrive the corresponding object under that path. Example:\
		 * \
		 * var a = { a : 1, b : { c: 2, d: [0, 1] } };\
		 * \
		 * print($$(a).get("b.c")); // 2\
		 * sprint($$(a).get("b.d")); // [0, 1]\
		 * print($$(a).get("b.d[0]")); // 0\
		 * \
		 * </odoc>
		 */
		get: (aPath) => {
            if (!$$(aObj).isObject()) return void 0;

			aPath = aPath.replace(/\[(\w+)\]/g, '.$1');
			aPath = aPath.replace(/^\./, '');

			var a = aPath.split('.');
			for (var i = 0, n = a.length; i < n; ++i) {
				var k = a[i];
				if (k in aObj) {
					aObj = aObj[k];
				} else {
					return;
				}
			}
            return aObj;
		},
		/**
		 * <odoc>
		 * <key>$$(aObject).set(aPath, aNewValue) : Object</key>
		 * Given aObject it will try to parse the aPath a set the corresponding object under that path to aNewValue. Example:\
		 * \
		 * var a = { a : 1, b : { c: 2, d: [0, 1] } };\
		 * \
		 * sprint($$(a).set("b.c", 123); // { a : 1, b : { c: 123, d: [0, 1] } }\
		 * \
		 * </odoc>
		 */
		set: (aPath, aValue) => {
			if (!$$(aObj).isObject()) return void 0;
			var orig = aObj;

			aPath = aPath.replace(/\[(\w+)\]/g, '.$1');
			aPath = aPath.replace(/^\./, '');

			var a = aPath.split('.');
			var prev, prevK;
			for (var i = 0, n = a.length; i < n; ++i) {
				var k = a[i];
				prev = aObj;
				prevK = k;
				if (k in aObj) {
					aObj = aObj[k];
				} else {
					aObj[k] = {};
					aObj = aObj[k];
				}
			}
			prev[prevK] = aValue;
			return orig;
        },
        isDef: () => { return (!(typeof aObj == 'undefined')) ? true : false; },
        isUnDef: () => { return (typeof aObj == 'undefined') ? true : false; },
        isArray: () => { return Array.isArray(aObj); },
        isMap: () => { return (Object.prototype.toString.call(aObj) == "[object Object]"); },
        isObject: () => { var type = typeof aObj; return type === 'function' || type === 'object' && !!aObj; },
        isFunction: () => { return typeof aObj == 'function' || false; },
        isString: () => { return typeof aObj == 'string' || false; },
        isNumber: () => { return !isNaN(parseFloat(aObj)) && isFinite(aObj); },
        isDate: () => { return (null != aObj) && !isNaN(aObj) && ("undefined" !== typeof aObj.getDate); }
	};
	return _r;
};

const _$ = function(aValue, aPrefixMessage) {
    var defined;
    if ($$(aPrefixMessage).isDef()) aPrefixMessage += " "; else aPrefixMessage = "";
    if ($$(aValue).isDef()) defined = true; else defined = false;

    const __r = {
		// Defaults
        default : (aVal) => {
            if (!defined) return aVal; else return aValue;
        },
        $_ : (aMessage) => {
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "not available";
			if (!defined) throw aMessage;
			return aValue;
		},

		// Type check
        isNumber: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a number";
            if (defined && !$$(aValue).isNumber()) throw aMessage;
            return __r;
        },
        isString: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a string";
            if (defined && !$$(aValue).isString()) throw aMessage;
            return __r;
        },
        isBoolean: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not boolean";
            if (defined && (typeof aValue !== "boolean")) throw aMessage;
            return __r;
        },
        isArray: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not an array";
            if (defined && !$$(aValue).isArray()) throw aMessage;
            return __r;
        },
        isMap: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a map";
            if (defined && !$$(aValue).isMap()) throw aMessage;
            return __r;
		},
		isJavaObject: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not a java object";
            if (defined && !isJavaObject(aValue)) throw aMessage;
            return __r;
		},
		isInstanceOf: (aClass, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not an instance of " + aClass;
            if (defined && !(aValue instanceof aClass)) throw aMessage;
            return __r;
		},

		// Generic validations
        check: (aFunction, aMessage) => {
			if (!$$(aFunction).isFunction() && !$$(aFunction).isString()) throw "please provide a function to check";
            var res = ($$(aValue).isFunction() ? aFunction(aValue) : (new Function('v', 'return ' + aFunction))(aValue));
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not ok";
            if (defined && !res) throw aMessage;
            return __r;
        },
        expr: (aEval, aMessage) => {
			if (!$$(aEval).isString()) throw "please provide an expression";
            var res = af.eval(templify(aEval, { v: aValue }));
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not ok";
            if (defined && !res) throw aMessage;
            return __r;
		},
		equals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is equals to " + aVal;
            if (defined && aValue == aVal) throw aMessage;
            return __r;
        }        ,
        notEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not equals to " + aVal;
            if (defined && aValue != aVal) throw aMessage;
            return __r;
		},
		anyOf: (aVals, aMessage) => {
			if (!$$(aVals).isArray()) throw "please provide an array of values";
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "has a value not in " + JSON.stringify(aVals);
			if (defined && $$(aValue).isArray()) {
				aValue.forEach((v) => {
					if (aVals.indexOf(v) < 0) throw aMessage;
				});
            }
            return __r;
		},
		oneOf: (aVals, aMessage) => {
			if (!$$(aVals).isArray()) throw "please provide an array of values";
			if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not one of " + JSON.stringify(aVals);
            if (defined && !$$(aValue).isArray() && aVals.indexOf(aValue) < 0) throw aMessage;
            return __r;
		},

		// Numeric validations
        between: (aValA, aValB, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not between " + aValA + " and " + aValB;
            if (defined && (aValue < aValB && aValue > aValA)) throw aMessage;
        },
        betweenEquals: (aValA, aValB, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not between " + aValA + " and " + aValB;
            if (defined && (aValue <= aValB && aValue >= aValA)) throw aMessage;
        },
        less: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is less than " + aVal;
            if (defined && aValue > aVal) throw aMessage;
            return __r;
        },
        lessEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is less or equals than " + aVal;
            if (defined && aValue >= aVal) throw aMessage;
            return __r;
        },
        greater: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is greater than " + aVal;
            if (defined && aValue < aVal) throw aMessage;
            return __r;
        },
        greaterEquals: (aVal, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is greater or equals than " + aVal;
            if (defined && aValue <= aVal) throw aMessage;
            return __r;
        },

		// String validations
        notEmpty: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is empty";
            if (defined && String(aValue) == "") throw aMessage;
            return __r;
        },
        empty: (aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "is not empty";
            if (defined && String(aValue) != "") throw aMessage;
            return __r;
        },
        contains: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if contains";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't contain " + aVal;
            if (defined && String(aValue).indexOf(aVal) < 0) throw aMessage;
            return __r;
        },
        notContains: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if not contains";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "contains " + aVal;
            if (defined && String(aValue).indexOf(aVal) >= 0) throw aMessage;
            return __r;
        },
        starts: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it starts with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't start with '" + aVal + "'";
            if (defined && !(aValue.startsWith(aValu))) throw aMessage;
            return __r;
        },
        ends: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it ends with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't end with '" + aVal + "'";
            if (defined && !(aValue.endsWith(aVal))) throw aMessage;
            return __r;
        },
        notStarts: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it not starts with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "starts with '" + aVal + "'";
            if (defined && (aValue.startsWith(aValu))) throw aMessage;
            return __r;
        },
        notEnds: (aVal, aMessage) => {
			if (!$$(aVal).isString()) throw "please provide a string to check if it not ends with";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "ends with '" + aVal + "'";
            if (defined && (aValue.endsWith(aVal))) throw aMessage;
            return __r;
        },
        regexp: (aRegExp, aMessage) => {
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't match '" + aRegExp + "'";
            if (!(aRegExp instanceof RegExp)) throw "is not a regular expression (" + aRegExp + ")";
            if (defined && !aRegExp.test(aValue)) throw aMessage;
            return __r;
        },
        javaRegexp: (aRegExp, aMods, aMessage) => {
			if ($$(aRegExp).isUnDef() || !$$(aRegExp).isString()) throw "please provide a regular expression string";
            if ($$(aMessage).isUnDef()) aMessage = aPrefixMessage + "doesn't match '" + aRegExp + "'";
            if (defined && !javaRegExp(aValue).test(aRegExp, aMods)) throw aMessage;
            return __r;
        }
    };
    return __r;
};
<|endoftext|>